- 参考书籍:<<大话数据结构>>--邻接表
- 简单的说:用一个结构体存链表头,链表头连接一个链表。 有几条链表,就用几个数组。
- 下面的代码:
- chainTableHead中firstson存链表头,sonCount记录链表头对应的链表大小,a表示这个链表头的标识
-
chainTableNode则是一个链表
-
main中是简单的插入,删除的示例demo
- 应用场景:多个root证书,生成了多个CA证书,CA证书生成了多个用户使用的证书A。关系大概是:root-->CA1-->CA2-->A (其中CA1, CA2都算CA证书)。 需要把证书之间的关系理出来,并且把root证书对应证书链找到。其中chainTableHead存证书链的名字(int a) , firstson指向第一个root证书。链表存了root-->CA1-->CA2-->A
- 代码
//数组 + 单链表 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #define DataType int //单向链表 typedef struct chainTableNode { DataType data; struct chainTableNode* next; }chainTableNode; static chainTableNode *headNode = NULL, *tailNode = NULL; static int chainTableNodeCount = 0; //链表在last和next之间插入一个节点 chainTableNode* insertListNode(chainTableNode* last, chainTableNode* next) { // generate a node chainTableNode* newNode = (chainTableNode*) malloc(sizeof(chainTableNode)); // new node be pointed by last node if (last != NULL) {last->next = newNode;} // new node point to next node newNode->next = next; chainTableNodeCount++; return newNode; } //链表删除数据 void del_ListNode(chainTableNode* node) { if (node == headNode) { chainTableNode* tmp = headNode->next; free(headNode); headNode = tmp; if(--chainTableNodeCount == 0) { headNode = NULL; tailNode = NULL; } return; } chainTableNode* next; chainTableNode* last = NULL, *nodeTmp=NULL; { // get next node next = node->next; // get last node for (nodeTmp = headNode; nodeTmp != NULL; (nodeTmp = nodeTmp->next)) { if (nodeTmp->next == node) last = nodeTmp; } // link last node to next node if (last) last->next = next; } // update tailnode val if (node == tailNode) { tailNode = last; } free(node); chainTableNodeCount--; return; } //链表打印数据 void printfData(DataType* data) { printf("val [%d]\n", *data); } // print all list val void printfListVal() { chainTableNode* node; int a = 0; printf("===============chaintable head %p count %d\n", headNode, chainTableNodeCount); for (node = headNode; node != NULL; (node = node->next)) { printf("node %p-->%p--\n", node, node->next); } for (node = headNode; node != NULL; (node = node->next)) { printf("node = [%p] ", node); printfData(&node->data); } printf("===============chaintable tail %p\n", tailNode); } //链表尾插法 chainTableNode* create_NodeatTail(DataType data) { chainTableNode* tmp = NULL; if (!headNode) { headNode = insertListNode(NULL, NULL); tailNode = headNode; tmp = headNode; } else { tmp = insertListNode(tailNode, NULL); tailNode = tmp; } memcpy(&tmp->data, &data, sizeof(DataType)); return tmp; } //链表:在last和next之间插入节点并赋值 void create_NodeafterNode(DataType* data, chainTableNode* last, chainTableNode* next) { chainTableNode* tmp = insertListNode(last, next); memcpy(&tmp->data, data, sizeof(DataType)); } //邻接表 // chainTableHead作为指向链表头的节点 typedef struct chainTableHead { int a; int sonCount; // 链表个数 chainTableNode* firstson; // 第一个链表 } chainTableHead; #define MAX_HEAD_NUM 10 static chainTableHead* headNodeArray[MAX_HEAD_NUM] = {NULL}; void printfNodeVal() { char data[512] = {'\0'}; for (int i = 0; i < MAX_HEAD_NUM; i++) { if (headNodeArray[i]) { snprintf(data, 512, "head pos [%d] val[%d]", i, headNodeArray[i]->a); printf("%s",data); if (headNodeArray[i]->firstson) { snprintf(data, 512," firstson[%p]", headNodeArray[i]->firstson); printf("%s",data); } printf("\n"); headNode = headNodeArray[i]->firstson; chainTableNodeCount = headNodeArray[i]->sonCount; printfListVal(); printf("\n"); headNode = NULL; } } } bool create_ChildTailNode(int pos, chainTableNode* son) { int ret = false; static int firstFlag[MAX_HEAD_NUM] = {1,1,1,1,1,1,1,1,1,1}; // prepare data headnode and count headNode = headNodeArray[pos]->firstson; chainTableNodeCount = headNodeArray[pos]->sonCount; // cretate node chainTableNode* tmp = NULL; if (son) { tmp = create_NodeatTail(son->data); ret = true; } else { ret = false; } // update head firstnode if (firstFlag[pos]) { headNodeArray[pos]->firstson = tmp; firstFlag[pos] = 0; } // update head soncount headNodeArray[pos]->sonCount = chainTableNodeCount; headNode = NULL; return ret; } // 删除第pos个链表的数据 bool del_ChildNode(int pos, DataType data) { chainTableNode* tmp = NULL; // find data in chainTablep[pos] if (headNodeArray[pos]) { for (tmp = headNodeArray[pos]->firstson; tmp != NULL; tmp = tmp->next) { if (tmp->data == data) { break; } } } if (tmp) { headNode = headNodeArray[pos]->firstson; chainTableNodeCount = headNodeArray[pos]->sonCount; del_ListNode(tmp); headNodeArray[pos]->firstson = headNode; headNodeArray[pos]->sonCount = chainTableNodeCount; } else { printf("didn't find [%d] in chainTable\n", data); } } void create_TreeHeadNode(int pos, int value, chainTableNode* son) { if (pos > MAX_HEAD_NUM || pos < 0) { printf("over MAX_HEAD_NUM \n "); return; } if (!headNodeArray[pos]) { // create first chainTableHead headNodeArray[pos] = (chainTableHead*)malloc(sizeof(chainTableHead)); headNodeArray[pos]->a = value; // create childnode with son chainTableNodeCount = 0; if (son && create_ChildTailNode(pos, son)) { headNodeArray[pos]->sonCount = chainTableNodeCount; } else { printf("create tailnode null or error \n "); } } else { printf("del headnode first \n "); } } int main() { { // chainTableNode son = { // .data = 20, // .next = NULL, // }; // create_TreeHeadNode(0, 2, &son); // chainTableNode son22 = { // .data = 32, // .next = NULL, // }; // create_ChildTailNode(0, &son22); // create_TreeHeadNode(1, 4, NULL); // chainTableNode son33 = { // .data = 32, // .next = NULL, // }; // create_ChildTailNode(1, &son33); // printfNodeVal(); } { chainTableNode son = { .data = 20, .next = NULL, }; create_TreeHeadNode(0, 2, &son); chainTableNode son22 = { .data = 32, .next = NULL, }; create_ChildTailNode(0, &son22); printfNodeVal(); del_ChildNode(0, 20); printfNodeVal(); del_ChildNode(0, 32); printfNodeVal(); } }