第二个一千行总结-数据结构C复习--知识点总结2--五到七章

第五章 数组与广义表

n维数组看作数据元素为n-1维数组的线性表

数组地址计算:略

特殊矩阵压缩:

三角矩阵;三对角矩阵(带状矩阵);

稀疏矩阵:存储数据总量小于百分之三十

稀疏矩阵用三元组(行,列,值)储存,定义如下:
typedef struct{
    int row, col;//行,列 
    int e;
}Triple;

typedef struct{
    Triple data[MAX+1];
    int m, n, len;//行,列,数据总个数 
}TSMtrix;

普通双for循环算法
void TransMatrix(int a[m][n], b[m][n]){
    int i, j;
    
    for(i = 0; i < m; i++)
        for(j = 0; j < n; j++)
            b[j][i] = a[i][j];    

稀疏矩阵递增转置法
void TransposeTSMatrix(TSMatrix A, TSMatrix *B){
    int i, j, k;
    
    B->m = A.n; B->n = A.m; B->len = A.len;
    //多次扫描,找到A列中对应B中的行的元素,一共扫描A.n次 
    if(B->len){
        j = 1;
        for(k = 1;k <= A.n;k++)//A.n为列数
            for(i=0 ;i < A.len;i++)               
                if(A.data[i].col == k)
                {
                    B->data[j].row = A.data[i].col;
                    B->data[j].col = A.data[i].row;
                    B->data[j].e = A.data[i].e;
                    j++;
                }
            
    }

//一次快速定位转置法
void FastTransposeTSMatrix(TSMatrix A, TSMatrix *B) {
    int col, i, j ,k;
    //值得注意的是Triple定义的数组data[]保存的是存在元素(非0元素),值为零的不存 
    int num[MAXSIZE],position[MAXSIZE];
    
    B->m = A.n; B->n = A.m; B->len = A.len;
    if(B->len){
        num[] = {0};
        //循环清0也可以
        for(t = 1;t <= A.len;t++)
            num[A.data[t].col]++;//统计第col列的数据个数 
            
        position[1] = 1;
        for(col = 2;col<=A.len;col++)//根据num每一列个数得到每一个新列第一个元素的位置 
            position[col] = position[col-1]+num[col-1]; //position为第几个元素
             
        for(p = 1;p         {
            col = A.data[p].col; 
            q = position[col];//找到该列第一个元素的位置 
            B->data[q].row = A.data[p].col;
            B->data[q].col = A.data[p].row;
            B->data[q].e = A.data[p].e;
            position[col]++;
            //下一个列号为col的非零元素再B中存放位置 
        }
    }
}

十字链表 
typedef ElemType int
typedef struct OLNode
{
    int col, row;
    ElemType value;
    struct OLNode *right, *down; 
}OLNode, *OLink;

typedef struct
{
    OLink *row_head, *col_head;//注意这个是行列头指针链表的指针数组 
    int m, n, len;                //行列长度 
}CrossList;

//建立十字链表
bool CreateCrossList(CrossList *M){
    //先输入矩阵M的相关信息 
    //为指针数组分配空间并且初始化
    //输入十字链表每个节点的相关信息
    //判断是否输入正确
    //正确则进行创建结点并且插入链表
    int m, n, len;
    int col, row;
    ElemType value;
    int i;
    OLink *q,*p;
     
    
    scanf(&m, &n, &len);
    M->len = len; M->m = m; M->n = n;
    
    if(!(M->row_head = (* OLink)malloc(m * sizeof(OLink)))) return false;
    if(!(M->col_head = (* OLink)malloc(n * sizeof(OLink)))) return false;
    //以下可以直接写M->row_head[ ] = NULL;
    for(i = 0; i < m; i++)
        M->row_head[i] = NULL;
    for(i = 0;i < n; i++)
        M->col_head[i] = NULL;
    
    for(scanf(&row, &col, &value); row != -1; scanf(&row, &col, &value))
    {
        if(!(p = (OLNode *)malloc(sizeof(OLNode)))) return false;
        p->col = col;
        p->row = row;
        p->value = value;
        //先插行再插列互相不干扰
        if(M->row_head[row] == NULL) 
            M->row_head[row] = p;
        else{
            q = M->row_head[row];
            while(q->right && q->right->row < row)
                q = q->right;
            //q此时指向该行链表最后一个元素
            //类似与尾插 
            p->right = q->right;
            q->right = p;
        }
        if(M->col_head[col] == NULL)
            M->col_head[col] = p;
        else{
            q = M->col_head[col];
            while(q->down && q->down->col < col){
                q = q->down;
            }
            p->down = q->down;
            q->down = p;
        }
    }

广义表:递归定义, 可以为无限序列(线性表为有限序列).表头为第一个元素,其余为表尾.
定义:
typedef enum{
    ATOM, LIST
}Elemtag;//atom为原子结点标志,list为表结点标志

typedef struct GLNode{
    ElemTag tag;
    
    union{//以下表明二选一 
        AtomType atom;
        struct{
            struct GLNode *hp, *tp;
        }htp;
    }atom_htp;
}GLNode , *GList;
广义表操作:略


第六章: 树与二叉树!!!!!!!!!!!

定义:根,子树,结点,度,高度(深度), 分支结点, 叶子节点, 森林, 孩子.兄弟.祖先.堂兄弟.子孙.双亲结点, 前/后辈.

 树的图解表示法 
 1.树形表示法(倒置树结构)
 2.文氏图表示法
 3.广义表示形式(嵌套括号表示法)
 4.凹入表示法    
 
二叉树!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
性质:第i层至多2^(i-1)个结点; 前k层至多2^(k-1)个结点.
叶子结点为n,度数为2结点为m,则n = m + 1. 
区别:!!!满二叉树和完全二叉树
完全二叉树为:其深度下的1~n的位置序号分别与等高的满二叉树一一对应. 其深度计算log2(n)向下取整+1
                                                            //相当于python里面的floor(log2(n)) log2(7)+1= 3

存储结构:
顺序存储结构:按照结点的层序编号以此存储到数组(向量)对应位置
链式存储结构:
定义如下:
typedef DataType int
typedef struct Node{
    DataType data;
    struct Node *LChild;
    struct Node *RChild;
}BiTNode, *BiTree; 

必考点!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!二叉树的遍历!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

遍历规则:大致按照左中右,然后先/中/后序列代表着访问根的先后顺序,先序就先访问 
先序遍历:先遍历根,再左子树,再右子树.
中序遍历:先遍历左子树,再根,再右子树.
后序遍历:...

应用广泛:表达式求值-->前缀表达式为波兰表达式, 后缀表达式为逆波兰表达式,后缀表达式易于求值

递归算法:
先/中/后序遍历只是访问根结点先后顺序不一样而已

//二叉树的遍历
//先序遍历 DLR 

void PreOrder(BiTree root){
    if(root != NULL){
        Visit(root->data);
        PreOrder(root->LChild);
        PreOrder(root->RChild);
    }
}
//中序遍历 LDR 
void InOrder(BiTree root){
    if(root != NULL){
        InOrder(root->LChild);
        Visit(root->data);
        InOrder(root->RChild);
    }
}

//后序遍历 LRD
void PostOrder(BiTree root){
    if(root != NULL){
        PostOrder(root->LChild);
        PostOrder(root->RChild);
        Visit(root->data); 
    }
}

//输出二叉树中的结点
void PreOrder(BiTree root){
    if(root != NULL){
        printf(root->data);
        PreOrder(root->LChild);
        PreOrder(root->RChild);
    }
}
//输出二叉树中的叶子结点 
//先序遍历
void PreOrder(BiTree root){
    if(root!= NULL){
        if(root->LChild == NULL && root->RChild == NULL)
            printf(root->data);
        PreOrder(root->LChild);
        PreOrder(root->RChild);
    }

//统计叶子节点的数目
//法1
//设置全局变量!!!!
int LeafCount =  0;
void leaf(BiTree root)
{
    leaf(root->LChild);
    leaf(root->RChild);
    if(root->LChild ==NULL && root->RChild == NULL){
        LeafCount++;
    }
 } 
 
 //法2 分治算法 这个有点妙! 
int leaf(BiTree root)
{
    if(root == NULL)
        LeafCount = 0;
    else if(root->LChild == NULL || root->RChild == NULL){
        LeafCount++;
    } 
    else
        LeafCount = leaf(root->LChild) + leaf(root->RChild);
    return LeafCount;
 } 
 
//建立二叉树链表方式储存二叉树
//扩展先序遍历方式创建二叉树链表
原理:一棵树先序遍历得到结点的所有值;那么一堆值根据先序遍历得到树 
void CreatBiTree(BiTree *bt){
    char ch;
    ch = getchar();
    
    if(ch == '.')
        *bt = NULL;
    else{
        *bt = (BiTree) malloc(sizeof(BiNode));
        (*bt)->data = ch;
        CreateBiTree(&(*bt)->LChild) ;
        CreateBiTree(&((*bt)->RChild);
    }

//求二叉树的高度
//后序遍历, 求高度, 递归
int PostTreeDepth(BiTree bt)
{
    int hl, hr, max;
    if(bt != NULL){
        hl = PostTreeDepth(bt->LChild);
        hr = PostTreeDepth(bt->RChild);
        max = hl > hr ? hl : hr;//三元运算符 
        return max +1 ;
    }
    else
        return 0;
 } 
 
//先序遍历实现
int depth = 0;
void PreTreeDepth(BiTree bt, int h){
    if(bt != NULL){
        if(h > depth) 
            depth = h;
        PreTreeDepth(bt->LChild, h+1);
        PreTreeDepth(bt->RChild, h+1);
    }
}

!!!!!!!!!!!!!!!!!!!!!!!!!!!!二叉树的层次遍历算法!!!!!!!!!!!!!很可能大题
void LevelOrder(BiTree bt){
    BiTree Queue[MAX];            //将队列与二叉树结合, 重点!!!!
    int front, rear;
    
    if(bt == NULL) return;
    front = rear = 0;
    
    Queue[rear] = bt;//根节点入队,队尾入队哈!
    rear++;//尾指针移走
    
    //当front!=rear即队列不为空
    while(rear != front){
        printf("%d", Queue[front]);//visit(xxx);//访问刚刚出队的元素 
        if(Queue[front]->LChild){
            Queue[rear] = Queue[front]->LChild;//存在左孩子则入队 
            rear++; 
        }
        if(Queue[front]->RChild){
            Queue[rear] = Queue[front]->RChild;
            rear++; 
        }
        front++;//出队的最后操作 
    } 

//基于栈的递归消除
//中序遍历二叉树的非递归算法
void inorder(BiTree root){
    Stack s[m];
    int top = 0;
    BiTNode *p;
    
    p = root;
    
    do{
        while(p != NULL){
            if(top > m) 
                return;
                // 栈满
            top++;
            s[top] = p;
            p = p->LChild;
            //遍历左子树 
        }
        if(top != 0){//栈空为0 
            p = s[top];
            top--;
            Visit(p->data);
            p = p->RChild;
        }
        
    }while(p != NULL || top != 0);
    //当前结点存在则入栈, 然后遍历左子树
    //不在, 退栈, 访问右子树 

//法2
//中序遍历非递归算法
void Inorder(BiTree root)
{
    Stack s;
    InitStack(&s);
    BiTNode *p = root;
    
    while(p != NULL || !IsEmpty(S))
    {//栈空, p指向NULL, 结束 
        if (p){
            Push(&S, p);
            p = p->LChild;
        }
        else
        {
            Pop(&s, &p);
            Visit(p->data);
            p = p->RChild;
        }
    }
 } 
 
//后序遍历二叉树的非递归算法
void PostOrder(BiTree root){
    BiTNode *p, *q;
    Stack S;
    q = NULL;
    p = root;
    Init(&Stack);
    
    while(p != NULL || !IsEmpty(S)){
        if(p){
            Push(&S, p);
            p = p->LChild;
        } 
        else{
            GetTop(&S, &p);
            if(p->RChild == NULL || p->RChild == q){//第二个条件判断是否也已经遍历过.类似于指针跟踪技术 
                visit(p->data);
                q = p;
                Pop(&S, &p);
                p = NULL;
            }
            else
                p = p->RChild;
        }
    }

//后序遍历法2
void PostOrder(BiTree root){
    Stack st;
    BiTNode *p, *q, *r;
    p = root;
    InitStack(&st);
    bool flag;
    
    do{
        while(p != NULL){
            Push(&st, &p);
            p = p->LChild;
        }
        r = NULL;
        flag = true;
        
        while(!IsEmpty(st) && flag){
            GetTop(&st, &p);
            if(p->RChild == r){
                Visit(p->data);
                Pop(&st, &p);
                r = p;
            }
            else{
                p = p->LChild;
                flag = false;
            }
        }
        
    }while(!IsEmpty(st));
    DestroyStack(st);


线索二叉树:
原理:n个结点的二叉树有2n个链域,而只有n-1条边(离散),n+1个链空浪费 

// LChild Ltag data Rtag RChild

typedef struct Node{
    int data;
    struct Node *LChild;
    struct Node *RChild;
    
    int Rtag;//0,指示结点的右孩子,1指示结点的遍历后继 
    int Ltag;//0,指示结点的左孩子,1指示结点的遍历前驱 
}BiTNode, *BiTree;


void Inthread(BiTree root){
    if(root != NULL){
        Inthread(root->LChild);//线索化左子树 
        if(root->LChild == NULL){
            root->Ltag = 1;
            root->LChild = pre;
        }
        if(pre != NULL && pre->RChild ==NULL){
            pre->RChild = root;
            pre->Rtag = 1;
        }
        pre = root;
        Inthread(root->RChild);
    }

//在中序线索树中找结点前驱
BiTNode *InPre(BiTNode *p){
    BiTNode *q, *pre;
    if(p->Ltag == 1) 
        pre = p->LChild;
    else{
        //在p的左子树中找最右下端点
        for(q = p->LChild; q->Rtag == 0; q = q->RChild)
            ;
        pre = q; 
    }
    return pre;
}


//在中序线索树中找后继结点 
BiTNode* InNext(BiTNode *p){
    if(p->Rtag == 1){
        Next = p->RChild;
    else{
        for(q = p->RChild; q->Ltag == 0; q = q->LChild)
            ;    
        Next = q;
    }
    return Next;
    }
}

//找中序遍历线索树第一个节点
BiTNode *InFirst(BiTNode *p){
    if(!p) return NULL;
    while(p->Ltag == 0) p = p->LChild;
    return p;
}
//遍历中序线索二叉树
void TInOrder(BiTNode Bt){
    BITNode *p;
    p = InFirst(Bt);
    while(p){
        visit(p);
        p = InNext(p);
    }

遍历确定二叉树:只有先序+中序, 后序+中序可以
尝试还原: 先序 ABCDEFGHI
          中序 BCAEDGHFI
          二叉树参考:
              A
        B------------D
         -C        E----------F
                         -G------I
                           -H

树的存储结构: 

//双亲表示法 
typedef struct TNode{
    int data;
    int parent;
}TNode;

typedef struct{
    TNode tree[MAX];
    int nodenum;
}ParentTree;

//孩子兄弟表示法 重点!!! 
typedef DataNode int
typedef struct ChildNode{//孩子链表结点定义 
    int Child;
    struct ChildNode *next;
}ChildNode;

typedef struct{//顺序表结点定义 
    DataNode data;
    ChildNode *FirstChild;
}DataNode;

typedef struct{
    DataNode nodes[MAX];
    int root;
    int num;
}ChildTree;

//孩子表示法 
tepedef struct CSNode{
    int data;
    struct CSNode *FirstChild;
    struct CSNode *NextChild;
}CSNode, *CSTree; 


森林,树,二叉树:
任意树转化为二叉树:兄弟加平行线,删右侧加线端点的与双亲的连线,旋转 
森林转化二叉树:第一颗二叉树不懂,后面的二叉树的根依次作为二前一棵二叉树的右孩子 

注意:树的先根遍历-->转换后二叉树的先序遍历
     树的后根遍历-->转换后二叉树的中序遍历 
 
树的遍历算法://孩子兄弟链表实现对树的先根遍历 
void RootFirst(CSTree root){
    if(root != NULL){
        Visit(root->data);
        p = root->FirstChild;
        while(p != NULL)
        {
            RpptFirst(p);
            p = p->NextSbling;
        }
    }

void RootFirst(CST root){
    if(root != NULL){
        Visit(root->data);
        RootFirst(root->FirstChild);
        RootFirst(root->NextSibling);
    }
}

哈夫曼树:带权叶子节点构成路径长度最短的二叉树,称最优二叉树 
路径,路径长度,结点的权,带权路径长度
类型定义:
#define N 20
#define M 2 * N -1
typedef struct{
    int weight;
    int parent;
    int LChild;
    int RChild;
}HTNode, HuffmanTree[M+1];

//Create the Tree
void CrtHuffmanTree(HuffmanTree ht, int w[], int n){
    //create ht[M+1], w[]存放n个权值
    for(i = 1; i <= n; i++)
        ht[i] = {w[i], 0, 0, 0};
    //Attention, start from 1, not 0 . So the length of ht is M + 1, not M.
    for(i = n + 1; n <= M; i++)
        ht[i] = {0, 0, 0, 0};
        
    for(i = n + 1; i <= M; i++){
        select(ht,i-1, &s1, &s2);
        //从ht[1]~ht[i-1]中选择两个parent = 0且weight最小的结点, 其序号赋值给s1, s2
        ht[i].weight = ht[s1].weight + ht[s2].weight;
        ht[s1].parent = i;
        ht[s2].parent = i;
        ht[i].LChild = s1;
        ht[i].RChild = s2;
    }

//对于第三个for 循环如下
for(i = n + 1; i <= M;i++ ){
    s1 = s2 = 32767;
    Inode = rnode = -1;
    for(k = 0; k <= i -1 ;k++){
        if(ht[k].parent == -1){
            if(ht[k].weight<= s1){
                s2 = s1; rnode = Inode;
                s1 = ht[k].weight; Inode = k;
            }
            else if(ht[k].weight <= s2){
                s2 = ht[k].weight; rnode = k;
            }
        }
    }
}

//哈夫曼编码_不用管,下一个可以看看 
void encoding(HuffmanTree ht, HuffmanCode hc, int n){
    //n 为叶子结点个数
    int start = n - 1;
    char *cd;
    cd = (char *)malloc((n + 1) * sizeof(char)); //暂时存入字符编码的字符数组 
    cd[n] = '\0';
    for(i = 1; i <= n; i++){
        start = n;
        c = i;
        p = ht[i].parent;
        while(p != -1){
            start--;
            if(ht[p].LChild == c)
                cd[start] = '0';
            else
                cd[start] = '1';
            c = p;
            p = ht[p].parent;//倒着存入的思想 
        }
        hc[i] = (char *)malloc((n+1-start) * sizeof(char));
        strcpy(hc[i], &cd[start]);
        cd = {'\0'};
    }
    free(cd); 

#define LEN 100
typedef struct{
    char ch;        //存储字符 
    char code[LEN]; //存放编码 
}TCode;//每个字符都对应唯一编码,因为哈夫曼树为前缀编码 
TCode CodeBook[LEN];//编码本 

//哈夫曼编码算法_2 
void encoding1(HTNode ht[], TCode book[], int n){
    char *str = (char *)malloc((n + 1) * sizeof(char));//存放编码 
    str[n] = '\0';
    int i, j, idx, p;
    //哈夫曼树某个叶结点下标idxa,用parent找到父节点idxb 
    for(i = 0; i < n; i++){//依次求叶子结点ht[i]的编码 
        book[i].ch = ht[i].ch;
        idx = i;
        j = n;
        while(p = ht[idx].parent > 0){
            if(ht[p].LChild == idx){
                j--;
                str[j] = '0';//左孩子 
            }
            else{
                j--;
                str[j] = '1';//右孩子 
            }
            idx = p;// idx 为下一轮找双亲的孩子,因为p = ht[idx].parent; 
        }
        strcpy(book[i].code, &str[j]);
    }
}
//解码运算算法 
void decoding(HTNode ht[], char *codes, int n){
    int p = 2 * n -2;//p为表中最后一个结点的指针, (总共2n-1个结点, 0开始), ht[p]代表root
    int i, j;
    i = 0;
    while(codes[i]!= '\0'){
        while(ht[p].LChild !=-1 && ht[p].RChild != -1){
            if(codes[i] == '0')
                p = ht[p].LChild;
            else
                p = ht[p].LChild;
            i++;
        }
        printf("%c", ht[p].ch);
        p = 2 * n -2;
    } 
}

第六章总结:

存储结构:
二叉树采用顺序储存与二叉链表储存
哈夫曼树概念,了解相关实现. 
遍历必考!

//icoding例题 
假设二叉树采用二叉链表方式存储, root指向根结点,node 指向二叉树中的一个结点,
编写函数 path,计算root到 node 之间的路径,(该路径包括root结点和 node 结点)。path 函数声明如下:
bool path(BiTNode* root, BiTNode* node, Stack* s);
其中,root指向二叉树的根结点,node指向二叉树中的另一结点,s 为已经初始化好的栈,
该栈用来保存函数所计算的路径,如正确找出路径,则函数返回 true,此时root在栈底,node在栈顶;
如未找到,则函数返回 false, 二叉树的相关定义如下:
typedef int DataType;
typedef struct Node{
    DataType data;
    struct Node* left;
    struct Node* right;
}BiTNode, *BiTree;
栈的相关定义及操作如下:
#define Stack_Size 50
typedef BiTNode* ElemType;
typedef struct{
    ElemType elem[Stack_Size];
    int top;
}Stack;
void init_stack(Stack *S); // 初始化栈
bool push(Stack* S, ElemType x); //x 入栈
bool pop(Stack* S, ElemType *px); //出栈,元素保存到px所指的单元,函数返回true,栈为空时返回 false
bool top(Stack* S, ElemType *px); //获取栈顶元素,将其保存到px所指的单元,函数返回true,栈满时返回 false
bool is_empty(Stack* S);  // 栈为空时返回 true,否则返回 false


#include "bitree.h" //请不要删除,否则检查不通过
#include
#include

bool path(BiTNode* root, BiTNode* node, Stack* s)
{
    BiTNode *p, *q; 
    int i = 0;

    p = root;
    q = NULL;
    init_stack(s);

    if (p == NULL || node == NULL)
        return false;
    if (p == node) {
        push(s, p);
        return true;
    }

    while (p != NULL || !is_empty(s)) {
        while (p) {
            push(s, p);
            if (p == node)
                return true;
            p = p->left;
        }
        top(s, &p); 
        if (p->right == q || p->right == NULL) {
            q = p;
            pop(s, &p);
            p = NULL; 
        } else {
            p = p->right;
        }
    }

    return false;
}


第七章 图

概念:vertex, head, arc, tail, edge.子图,邻接点,邻接边,度,入/出度,网,路径长度,回路,连通图.... 
分类:稀疏图,完全图,稠密图

图的存储结构://重点

//邻接表 
//分为表头结点表和边表
//前者是一个指针类型的结构数组 每一个结构包括结点域和链域
//边表储存弧结点, 弧结点结构分为三个域, 第一个储存弧结点相关信息, 
//第二个一般可以储存权重, 第三个链域存表头结点的下一个邻结点的弧 

#define MAX_VERTEX_NUM 20
typedef enum{DG, DN, UDG, UDN
} GraphKind;
typedef char VertexData

typedef struct ArcNode{//弧结点 
    int adj;
    int info; 
    struct ArcNode *nextarc;//指向下一条弧的指针 
}ArcNode;

typedef struct VertexNode{//表头结点 
    VertexData data;
    ArcNode *firstarc;
}VertexNode;

typedef struct{
    VertexNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnumber;
    GraphKind kind;
}AdjList;


//邻接矩阵
#define MAX_VERTEX_NUM 20
#define IFINITY
typedef enum{DG, DN, UDG, UDN
} GraphKind;
typedef char VertexData
typedef struct ArcNode{
    int adj;
}ArcNode;
typedef struct{
    VertexData vertex[MAX_VERTEX_NUM];
    ArcNode arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    int vexnum, arcnumber;
    GraphKind kind;
}AdjMatrix;

//求顶点位置函数 
int LocateVertex(AdjMatrix *G, VertexData v){
    int i = 0;
    for(; i < G->vexnum; i++){
        if(G->vertex[i] == v)
            return i; 
    }
    return -1;
}
//创建一个有向网 
int CreateDN(AdjMatrix *G){
    
    int vexnum, arcnum;
    VertexData v1, v2;
    int i, j, k, weight;
    
    scanf("%d, %d", &vexnum, &arcnum);
    for(i = 0; i< G->vexnum; i++)
        scanf("%c", &G->vertex[i]);
    for(i = 0; i < G->vexnum; i++)
        for(j = 0; j < G->vexnum; j++)
            G->arc[i][j] = IFINITY;
    for(k = 0; k < G->arcnumber; k++){
        scanf("%c, %c, %d", &v1, &v2, &weight);
        i = LocateVertex(G, v1);
        j = LocateVertex(G, v2);
        G->arc[i][j] = weight;
    }
    return OK;
}

//十字链表 
#define MAX_VERTEX_NUM 20
typedef enum{DG, DN, UDG, UDN
} GraphKind;
typedef char VertexData
typedef struct ArcNode{
    int tailvex;   //储存当前结点信息 
    int headvex;    //储存下一个结点信息 
    struct ArcNode *hlink;//入度 
    struct ArcNode *tlink;//出度, 相当于邻接表 
    int info;         //可以存权 
}ArcNode;
typedef struct VertexNode{
    VertexData data;    //顶点信息 
    ArcNode *firstin;    //入度的第一条弧//以该顶点为弧头的第一个弧顶点 
    ArcNode *firstout;  //以该顶点为弧尾的第一个弧顶点 
}VertexNode;

typedef struct{
    VertexNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnum;
    GraphKind kind;
}OrthList;

//创建十字链表算法 
void CrtOrthList(OrthList *g){
    
    int vexnum, arcnum;
    int i, j, k;
    VertexData vh, vt;
    ArcNode *p;
    
    scanf("%d, %d", &vexnum, &arcnum);
    g->vexnum = vexnum; g->arcnum = arcnum;
    
    for(i = 0; i < vexnum; i++){
        scanf("%c", &(g->vertex[i].data));
        g->vertex[i].firstin = NULL;
        g->vertex[i].firstout = NULL; 
    }
    
    for(k = 0; k < arcnum; k++){
        scanf("%c, %c", &vh, &vt);
        i = LocateVertex(g, vt);
        j = LocateVertex(g, vh);
        p = (ArcNode *)malloc(sizeof(ArcNode));
        p->tailvex = i;
        p->headvex = j;
        //类似于头插 
        p->tlink = g->vertex[i].firstout;
        g->vertex[i].firstout = p;
        p->hlink = g->vertex[j].firstin;
        g->vertex[j].firstin = p;
    }
}


//邻接多重表 
//邻接多重表与邻接表不同, 前者主要记录边的信息
//该表有标志域, 记录是否被搜索过, 两个顶点, 分别与两个顶点关联的边 
#define MAX_VERTEX_NUM 20
typedef enum{DG, DN, UDG, UDN
} GraphKind;
typedef char VertexData
typedef struct EdgeNode{
    int mark;
    int ivex, jvex;
    struct EdgeNode *ilink;
    struct EdgeNode *jlink;//用于指向下一条依附于顶点jvex的边 //顶点的邻接边 
}EdgeNode;
typedef struct{
    VertexData data;
    EdgeNode *firstedge; 
}VertexNode;
typedef struct{
    VertexNode vertex[MAX_VERTEX_NODE];
    int arcnum, vexnum;
    GraphKind kind;
}AdjMulList;


总结: 
//邻接矩阵:二维数组, 一维数组组成, 邻接矩阵存是否两个顶点之间有边 
//邻接表:顶点指针结构数组, 弧结点构成以顶点为头结点的链表 , 节省稀疏图对邻接矩阵造成的的空间浪费 
//邻接多重表:标志域, 两个结点域, 两个链域分别对应域两个顶点的邻接边信息 
//十字链表: 邻接表和逆邻接表的结合, 每一个结点有两个链域存出度和入度信息, 两个数据域存结点信息 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Abp VNext框架设计 - Masstransit分布式消息

abp 通过IDistributedEventBus接口集成自IEventBus实现分布式事件消息的发布订阅。IEventBus在什么时机触发PublishAsync?当前UnitOfWork完成时&#xff0c;触发IEventBus的PublishAsync在没有事务环境下&#xff0c;同步调用IEventBus的PublishAsyncabp 默认实现基于RabbitMq…

[蓝桥杯2018决赛]换零钞-枚举

题目描述 x星球的钞票的面额只有&#xff1a;100元&#xff0c;5元&#xff0c;2元&#xff0c;1元&#xff0c;共4种。 小明去x星旅游&#xff0c;他手里只有2张100元的x星币&#xff0c;太不方便&#xff0c;恰好路过x星银行就去换零钱。 小明有点强迫症&#xff0c;他坚持要…

16进制数用空格分开 tcp_面试时,你是否被问到过TCP/IP协议?

点击蓝字关注我们看到这句话&#xff0c;有没有感到很熟悉呀&#xff1f;相信很多人在面试的时候都被要求&#xff0c;很多人会觉得我们在实际开发中一般用不到这些知识&#xff0c;所以对这些东西不屑一顾。但是小编认为想要成为一个完美的网工,那么对这些基础知识必须要有一定…

直接使用汇编编写 .NET Standard 库

前言Common Language Runtime&#xff08;CLR&#xff09;是一个很强大的运行时&#xff0c;它接收 Common Intermediate Language&#xff08;CIL&#xff09; 的输入并最终产生机器代码并执行。CIL 在 CLR 上相当于 ASM 汇编代码的存在。CLR 之上的语言 C#、F#、VB.NET 等语言…

[蓝桥杯2016决赛]七星填数-next_permutation枚举

题目描述 如下图所示&#xff1a; 在七角星的14个节点上填入1~14 的数字&#xff0c;不重复&#xff0c;不遗漏。要求每条直线上的四个数字之和必须相等。 图中已经给出了3个数字。请计算其它位置要填充的数字&#xff0c;答案唯一。 填好后&#xff0c;请提交绿色节点的4个数…

python的argsort函数_python——argsort函数

numpy中argsort函数用法&#xff0c;有需要的朋友可以参考下。在Python中使用help帮助>>> import numpy>>> help(numpy.argsort)Help on function argsort in module numpy.core.fromnumeric:argsort(a, axis-1, kindquicksort, orderNone)Returns the indic…

第三个一千行+500行总结-数据结构C复习--知识点总结3--七到九章

第七章 (接知识点总结2) 图 图的遍历: //深度优先搜索 #define OK 1 #define True 1 #define Error -1 #define False 0 typedef enum{DG, DN, UDG. UDN}Graph; int visited[MAX]; //Graph代表图的一种存储结构比如邻接表,邻接矩阵 void TranverseGraph(Graph g){ int…

系统蓝屏的几种姿势,确定不了解下么?

前言在 蓝屏&#xff08;BSOD&#xff09;转储设置&#xff0c;看本文就够了&#xff01;这篇文章里比较详细的介绍了蓝屏转储设置。做好设置后&#xff0c;我们就可以在需要的时候使系统蓝屏了。本文介绍几种使系统蓝屏的办法&#xff0c;当然肯定还有其它办法&#xff0c;如果…

最长公共子串-dp

题目: 给定两个字符串&#xff0c;求出它们之间最长的相同子字符串的长度。 公共子串和公共子序列不同&#xff0c;公共子序列不要求连续&#xff0c;但公共子串必须是连续的。如: A “helloworld” B “loop” A和B的最长公共子序列是"loo",但最长公共子串是&quo…

the python challenge_The Python Challenge 谜题全解(持续更新)

Python Challenge(0-2)是个很有意思的网站&#xff0c;可以磨练使用python的技巧&#xff0c;每一关都有挑战&#xff0c;要编写相应的代码算出关键词&#xff0c;才可以获取下一关的url&#xff0c;还是很好玩的QAQLEVEL 0显然是计算图片中的\(2^{38}\)&#xff0c;结果为2748…

智能对话引擎:两天快速打造疫情问答机器人

01微软AI技术开源知识库疫情机器人近一个月来&#xff0c;“新冠肺炎疫情”成了所有人的热点话题&#xff0c;抗击疫情的战役在全国紧张有序地进行着。随着全国各地的企业陆续复工&#xff0c;怎样防范、保护自己和家人成了当下每个人的焦点。为了配合奋战在一线的医护人员打赢…

数码管

题目背景 小明的单片机上面的LED显示屏坏掉了&#xff0c;于是他请你来为他修显示屏。 屏幕上可以显示0~9的数字&#xff0c;其中每个数字由7个小二极管组成&#xff0c;各个数字对应的表示方式如图所示&#xff1a; 题目描述 为了排除电路故障&#xff0c;现在你需要计算&am…

fh 幅频特性曲线怎么画fl_初学者怎么练习线条?教你如何画出流畅线条的技巧...

初学者怎么练习线条&#xff1f;怎样才能画出流畅线条&#xff1f;画出流畅线条有哪些技巧&#xff1f;想必这些问题都是绘画初学者们比较伤脑筋的问题&#xff0c;那么到底怎样才能画出流畅线条呢&#xff1f;今天灵猫课堂老师就在网络上收集整理了关于初学者怎么练习线条&…

.NET Core开发实战(第12课:配置变更监听)--学习笔记

12 | 配置变更监听&#xff1a;配置热更新能力的核心这一节讲解如何使用代码来监视配置变化并做出一些动作当我们需要追踪配置发生的变化&#xff0c;可以在变化发生时执行一些特定的操作配置主要提供了一个 GetReloadToken 方法&#xff0c;这就是跟踪配置的关键方法接着使用上…

icoding复习1,2

icoding复习 1 链表 倒数查找 1. 已知一个带有表头结点的单链表, 假设链表只给出了头指针L。在不改变链表的前提下&#xff0c;请设计一个尽可能高效的算法&#xff0c; 查找链表中倒数第k个位置上的结点&#xff08;k为正整数&#xff09;。 函数原型为&#xff1a;int lnk_s…

密电破译-dp

题目背景 墨家家主召集弟子的原因是因为截获了密电并破获了重大情报&#xff0c;“公主薨&#xff0c;国王失踪&#xff0c;墨家即将面临灭顶之灾”。 题目描述 密电是由大小写字母组成字符串&#xff0c;密电之所以能破译是因为墨家掌握了破解方法&#xff0c;密钥是一个整数…

ASP.NET Core Web API基于RESTFul APIs的集合结果过滤和分页

译者荐语&#xff1a;如何在RESTFul APIs中进行集合结果分页&#xff1f;还是用客户端来拼接链接地址么&#xff1f;原文来自互联网&#xff0c;由长沙DotNET技术社区【邹溪源】翻译。如译文侵犯您的版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。在ASP.NET Co…

icoding复习6 图

icoding复习6 1. 邻接表1 试在邻接表存储结构上实现图的基本操作 insert_vertex 和 insert_arc&#xff0c;相关定义如下&#xff1a; typedef int VertexType; typedef enum{ DG, UDG }GraphType; typedef struct ArcNode{ int adjvex; InfoPtr *info; stru…

python帮助系统函数_【Python】【基础知识】【内置函数】【help的使用方法】

原英文帮助文档&#xff1a;help([object])Invoke the built-in help system. (This function is intended for interactive use.) If no argument is given, the interactive help system starts on the interpreter console. If the argument is a string, then the string i…

统计二进制数-dp

题目描述 输入一个正整数m,请输出从0到m中每一个数字二进制数中含有1的个数的总和,由于数值较大结果需要模100000. 输入格式 一个m 输出格式 二进制数中含有1的个数的总和s 输入输出样例 输入 2 输出 2 输入 5 输出 7 说明/提示 样例说明 20%的数据 m<500 50%的数据 m<…