数据结构 线性链表 模拟队列
1、头文件seqlist.h
1 #ifndef __SEQLIST_H__ 2 #define __SEQLIST_H__ 3 #include <stdio.h> 4 5 typedef void SeqList; // 定义一个链表类型 6 typedef void SeqListNode; // 定义链表结点 7 8 SeqList* Creat_SeqList(int capcity); // 根据容量创建链表 9 10 void Destory_SeqList(SeqList* list); // 销毁链表 11 12 void Clear_SeqList(SeqList* list); // 清空链表 13 14 int GetLen_SeqList(SeqList* list); // 获取链表长度 15 16 int GetCap_SeqList(SeqList* list); // 获取链表容量 17 18 int InsertNode_SeqList(SeqList* list,SeqListNode* node,int pos);// 在链表pos位置插入一个节点node 19 20 SeqListNode* GetNode_SeqList(SeqList* list,int pos); // 根据pos获取链表节点 21 22 SeqListNode* Delete_SeqList(SeqList* list,int pos); // 根据pos删除链表节点 23 24 #endif
2、seqlist.c实现接口
1 #include "seqlist.h" 2 #include <stdlib.h> 3 #include <string.h> 4 5 6 // 定义节点 7 // 在结构体中套一级指针 8 typedef struct _Tag_TSeqList{ 9 int length; 10 int capcity; 11 unsigned int* p; // 定义的是一个链表类型结构 12 }TSeqList; 13 14 15 // 根据容量创建链表 16 SeqList* Creat_SeqList(int capcity) 17 { 18 TSeqList* tmp = NULL; 19 tmp = (TSeqList*)malloc(sizeof(TSeqList)); 20 if(capcity < 0){ 21 printf("input capcity err\n"); 22 return NULL; 23 } 24 if(tmp == NULL){ 25 printf("func malloc failed\n"); 26 return NULL; 27 } 28 memset(tmp,0,sizeof(TSeqList)); 29 // 根据容量capcity分配节点大小 30 tmp->p = (unsigned int*)malloc(sizeof(unsigned int*) * capcity); 31 if(tmp->p == NULL){ 32 printf("func malloc tmp->p failed \n"); 33 return NULL; 34 } 35 tmp->capcity = capcity; 36 tmp->length = 0; 37 return tmp; // 返回的是个空链表 // 需要注意的是malloc内存后,并没有释放内存,因此数据还是存在内存中; 38 } 39 40 // 销毁链表 41 void Destory_SeqList(SeqList* list) 42 { 43 TSeqList* tlist = NULL; 44 if(list == NULL){ 45 printf("func return list is NULL\n"); 46 return; 47 } 48 tlist = (TSeqList*)list; 49 // 销毁链表,创建的时候malloc 两次tmp = (TSeqList*)malloc(sizeof(TSeqList));、 50 // tmp->p = (unsigned int*)malloc(sizeof(unsigned int*) * capcity); 51 // 因此需要释放两次 52 if(tlist->p != NULL){ 53 free(tlist->p); // 释放链表节点空间 需要先释放内部数据,在释放整体 54 } 55 free(tlist); // 释放链表空间 56 return ; 57 } 58 // 清空链表 链表回到初始化状态 59 void Clear_SeqList(SeqList* list) 60 { 61 TSeqList* tlist = NULL; 62 if(list == NULL){ 63 printf("list is NULL clear failed\n"); 64 return ; 65 } 66 tlist = (TSeqList*)list; // 将list清空空 67 tlist->length = 0; // list长度为0 68 } 69 // 获取链表长度 70 int GetLen_SeqList(SeqList* list) 71 { 72 TSeqList* tlist = NULL; 73 if(list == NULL){ 74 printf("list is NULL return\n"); 75 return -1; 76 } 77 tlist = (TSeqList*)list; 78 return tlist->length; /// 返回链表长度 79 } 80 // 获取链表容量 81 int GetCap_SeqList(SeqList* list) 82 { 83 TSeqList* tlist = NULL; 84 if(list == NULL){ 85 printf("list is NULL return\n"); 86 return -1; 87 } 88 tlist = (TSeqList*)list; 89 return tlist->capcity; // 返回链表容量 90 } 91 // 在链表pos位置插入一个节点node 92 int InsertNode_SeqList(SeqList* list,SeqListNode* node,int pos) 93 { 94 int i = 0; /// 定义节点索引 95 TSeqList* tlist = NULL; 96 if(list == NULL||node == NULL|| pos < 0){ 97 printf("input parameter err\n"); 98 return -1; 99 } 100 tlist = (TSeqList*)list; 101 if(tlist->capcity <= tlist->length){ 102 printf("list is full insert failed\n"); 103 return -2; 104 } 105 // 插入位置超前了 冗余处理 106 if(tlist->length <= pos){ 107 pos = tlist->length; 108 } 109 // 元素移动 110 for(i = tlist->length;i<pos;i++){ 111 tlist->p[i] = tlist->p[i-1]; 112 } 113 // 插入元素 114 tlist->p[i] = (unsigned int)node; 115 tlist->length++; // 链表长度递增 116 return 0; 117 } 118 // 根据pos获取链表节点 119 SeqListNode* GetNode_SeqList(SeqList* list,int pos) 120 { 121 TSeqList* tlist = NULL; 122 SeqListNode* node = NULL; 123 if(list == NULL){ 124 printf("list is NULL\n"); 125 return NULL; 126 } 127 tlist = (TSeqList*)list; 128 if(tlist->length < pos|| pos < 0){ 129 printf("input pos err\n"); 130 return NULL; 131 } 132 node = (SeqListNode*)tlist->p[pos]; 133 return node; 134 } 135 // 根据pos删除链表节点 136 SeqListNode* Delete_SeqList(SeqList* list,int pos) 137 { 138 TSeqList* tlist = NULL; 139 SeqListNode* tmp = NULL; 140 int i = 0; 141 if(list == NULL){ 142 printf("list is NULL\n"); 143 return NULL; 144 } 145 tlist = (TSeqList*)list; 146 if(tlist->length < pos || pos < 0){ 147 printf("input pos err\n"); 148 return NULL; 149 } 150 tmp = (SeqListNode*)tlist->p[pos]; 151 for(i=pos+1;i<tlist->length;i++){ 152 tlist->p[i-1] = tlist->p[i]; 153 } 154 tlist->length++; 155 return tmp; 156 }
3、main.c线性表测试
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "seqlist.h" 4 5 // 定义自己的数据体 6 typedef struct _Teacher{ 7 int age; 8 char *name; 9 }Teacher; 10 11 int main() 12 { 13 SeqList* list = NULL; 14 Teacher t1,t2,t3,t4; 15 int ret = 0,i = 0; 16 17 t1.age = 21; t1.name = "LiMing"; 18 t2.age = 23; t2.name = "WangWu"; 19 t3.age = 26; t3.name = "LiuHua"; 20 t4.age = 27; t4.name = "YangQing"; 21 22 // 创建一个链表 23 list = Creat_SeqList(10); 24 if(list == NULL){ 25 printf("Creat list failed \n"); 26 return -1; 27 } 28 ret = InsertNode_SeqList(list,(SeqListNode*)&t1,0); 29 ret = InsertNode_SeqList(list,(SeqListNode*)&t2,0); 30 ret = InsertNode_SeqList(list,(SeqListNode*)&t3,0); 31 ret = InsertNode_SeqList(list,(SeqListNode*)&t4,0); 32 33 // 遍历链表 34 for(i = 0;i < GetLen_SeqList(list);i++){ 35 Teacher* tmp = (Teacher*)GetNode_SeqList(list,i); 36 if(tmp == NULL) 37 return -2; 38 printf("name:%s...age:%d\n",tmp->name,tmp->age); 39 } 40 41 return 0; 42 }
4、在测试的时候,发现VS2012可以运行。但是使用gcc编译的时候,代码的强制类型转换,给出警告了,并且执行的时候出错;
5、多文件编译
gcc seqlist.c main.c -o output.out
6、链表的链式存储
结构体+结构体指针+数据域封装
#include <stdio.h> #include <stdlib.h> // 自定义节点类型 typedef struct node{ int data; // 数据域 struct node* next; // 指针域 存储节点的地址 }Node; void main() { int tmp; Node * head,*p,*last; head = p = last =NULL; printf("请输入数据,输入0结束\n"); scanf("%d",&tmp); while(tmp !=0 ) { p = (Node*)malloc(sizeof(Node)); // 新节点分配内存 p->data = tmp; // 保存数据 if(head == NULL){ // 第一个节点 head = p; // 保存第一个节点的地址 }else{ // 不是第一个节点 last->next = p; // 上一个节点的next保存下一个节点的地址 } last = p; // last指针变量始终保存最后有个节点的地址,last向后移动 printf("请输入数据,输入0结束\n"); scanf("%d",&tmp); } last->next = NULL; // 新节点增加完成后,最后一个节点的next指向NULL p = head; // 从头开始遍历 while(p != NULL) { printf("输入的数据为:%d\n",p->data); p = p->next; // 指针变量向后移动 } getchar(); getchar(); // 用于程序暂停 }
7、使用链表模拟队列
队列模型:队列中的数据,首先进入的首先出去;FIFO
定义数据结构:
// 队列中数据节点的数据结构 typedef int Item; typedef struct node{ Item item; struct node * pNext; }Node; // 保存队列中队列首尾的位置 typedef struct queue{ Node * front; // 队列的首指针 Node * rear; // 队列尾指针 int itemNum; // 队列中项目个数 }Queue;
定义队列操作接口:
#define MAXQUEUE 10 // 队列中最大数据节点数 /* 初始化一个空队列 */ void InitalizeQueue(Queue * qe); /* 判断队列是否满了,满了返回True,否则false */ unsigned int QueueIsFull( Queue *qe); /* 检查队列是否为空, 为空返回True否则返回false */ unsigned int QueueIsEmpty(const Queue* qe); /* 确定队列中项目的个数, 返回队列中项目个数 */ unsigned int GetQueueItemCount(const Queue* qe); /* 向队列尾部添加项目,添加成功返回True,否则返回false */ unsigned int AddItemEndQueue(Item item, Queue* qe); /* 从队列首端清除一个Item,成功返回True,否则返回false */ /* 队列中第一个Item复制到item中,然后删除队列中的item */ unsigned int DeleteFirstItemQueue(Item* item, Queue* qe); /* 清空队列 */ void EmptyQueue(Queue * qe);
队列接口实现:

/* 初始化一个空队列 */ void InitalizeQueue(Queue* qe) { qe->front = qe->rear = NULL; qe->itemNum =0; } /* 判断队列是否满了,满了返回1,否则0 */ unsigned int QueueIsFull(Queue *qe) { if(qe->itemNum < MAXQUEUE) return 0; else return 1; } /* 检查队列是否为空, 为空返回1,否则返回0 */ unsigned int QueueIsEmpty(const Queue* qe) { if(qe->itemNum == 0) return 1; else return 0; } /* 确定队列中项目的个数, 返回队列中项目个数 */ unsigned int GetQueueItemCount(const Queue* qe) { return qe->itemNum; } /* 向队列尾部添加节点,添加成功返回0,否则返回1 */ unsigned int AddItemEndQueue(Item item, Queue* qe) { Node* pNode; if(QueueIsFull(qe)) return 1; pNode = (Node*)malloc(sizeof(Node)); if(pNode == NULL){ printf("malloc node memory failed\n"); return 2; } pNode->item = item; pNode->pNext = NULL; if(QueueIsEmpty(qe)){ qe->front = pNode; }else{ qe->rear->pNext = pNode; // node 添加在链表的末端 } // 需要保存队列的最后地址 qe->rear = pNode; // 队列中的节点数量增加 qe->itemNum++; return 0; } /* 从队列首端清除一个Item,成功返回0,否则返回其他数 */ /* 队列中第一个Item复制到外部,然后删除队列中的item */ unsigned int DeleteFirstItemQueue(Item* item, Queue* qe) { Node* pTmp; if(QueueIsEmpty(qe)) return 1;// 队列为空 *item = qe->front->item; // 将数据返回到外部 pTmp = qe->front; qe->front = qe->front->pNext; free(pTmp); // 释放掉节点 qe->itemNum--; if(QueueIsEmpty(qe)) qe->rear = NULL; return 0; } /* 清空队列 */ void EmptyQueue(Queue * qe) { Item item; while(QueueIsEmpty(qe)) DeleteFirstItemQueue(&item, qe); }
队列接口测试:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include "myQueue.h" int main() { Queue line; Item item; char ch; InitalizeQueue(&line); puts("Test queue interface, Type a to add item, Type d to delete item"); puts("Type q to exit program"); while( (ch= getchar()) != 'q') { if(ch != 'a' && ch!= 'd') { if(ch == 'q') break; continue; } if(ch == 'a') { // 添加元素 printf("Interge to add:\n"); scanf("%d", &item); if(!QueueIsFull(&line)) // 队列非满 { printf("add item %d into queue",item); AddItemEndQueue(item,&line); }else{ // 队列满了 puts("queue is full"); } }else{ // 删除元素 if(QueueIsEmpty(&line)) puts("Nothing to delete"); else{ DeleteFirstItemQueue(&item, &line); printf("Remove item %d from queue", item); } } printf("%d items in the queue\n", GetQueueItemCount(&line)); puts("Type a to add item, d to delete item, q to quit"); } EmptyQueue(&line); puts("Bye...\n"); getchar(); return 0; }
8、二叉树
1、接口封装

#ifndef __TREE_H__ #define __TREE_H__ typedef struct item{ char PetName[16]; char PetKind[16]; }Item; typedef struct node{ Item item; struct node* Lift; struct node* Right; }Node; typedef struct tree{ Node *Root; int size; }Tree; #define MAXITEM 10 /* 初始化树为空树 */ void InitTree(Tree* tree); /* 判断树是否为空 空:0,非空:1*/ unsigned int TreeIsEmpty(const Tree* tree); /* 判断树是否为满 满:0,非满:1*/ unsigned int TreeIsFull(const Tree* tree); /* 获取树中,项目节点的个数 */ unsigned int TreeGetItemCount(const Tree* tree); /* 向树中添加一个节点项目 */ unsigned int TreeAddItem(const Item* item, Tree* tree); /* 在树中查找一个节点项目 */ unsigned int TreeFindItem(const Item* item, const Tree* tree); /* 在树中删除一个节点项目 */ unsigned int TreeDeleteItem(Item* item, Tree* tree); /* 把一个函数作用于树中所有项目 */ unsigned int TreeTraverseItem(Tree* tree, void (*pFunc)(Item *item)); /* 删除树中所有节点 */ void TreeDelAllItem(Tree* tree); #endif
2、接口实现

#include <stdio.h> #include <stdlib.h> #include "Tree.h" /* 二叉树的属性: 1、 */ typedef struct pair{ Node* child; Node* parent; }Pair; static Node* MakeNode(const Item* item) { Node* pNode; pNode = (Node*)malloc(sizeof(Node)); if(pNode != NULL){ pNode->Lift = NULL; pNode->Right = NULL; pNode->item = *item; } return pNode; } // 判断树中是否已经有将要添加的新节点 static Pair SeekItem(const Item* item, const Tree* tree) { } static unsigned int TreeAddNode(const Item* item, const Node* node) { return 0; } /* 初始化树为空树 */ void InitTree(Tree* tree) { } /* 判断树是否为空 空:0,非空:1*/ unsigned int TreeIsEmpty(const Tree* tree) { return 0; } /* 判断树是否为满 满:0,非满:1*/ unsigned int TreeIsFull(const Tree* tree) { return 0; } /* 获取树中,项目节点的个数 */ unsigned int TreeGetItemCount(const Tree* tree) { return 0; } /* 在树中添加项目节点 */ unsigned int TreeAddItem(const Item* item, Tree* tree) { Node* newNode; // 判断树中是否有节点空位 if(TreeIsFull(tree)) { printf("the tree is full \n"); return -1; } // 判断树中是否已经有将要添加的节点 if(SeekItem(item, tree).child != NULL) { printf("attemp"); return -2; } // 创建新节点,并幅值左右节点 newNode = MakeNode(item); if(newNode == NULL) { printf("create new Node failed\n"); return -3; } // 成功创建新节点 tree->size++; if(tree->Root == NULL) // 空树 tree->Root = newNode; else TreeAddNode(item,tree->Root); return 0; } /* 在树中寻找项目节点 */ unsigned int TreeFindItem(const Item* item, const Tree* tree) { return 0; } /* 树中删除项目节点 */ unsigned int TreeDeleteItem(Item* item, Tree* tree) { return 0; } /* 将一个函数作用于所有节点 */ unsigned int TreeTraverseItem(Tree* tree, void (*pFunc)(Item *item)) { return 0; } /* 删除树中所有节点 */ void TreeDelAllItem(Tree* tree) { }
3、接口测试

#include <stdio.h> #include "Tree.h" int main() { return 0; }
【推荐】FlashTable:表单开发界的极速跑车,让你的开发效率一路狂飙
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步