C语言实现链表的基本操作(增删改查)

时间:2025-03-15 10:58:11
#include <> #include <> #include <> #include <> // 链表的节点必须包含两个信息“有效数据和指针”,也就是“数据域和指针域 ” typedef struct Node { //数据域 int data; //指针域 struct Node *pNext;//链表中的指针,指向的是下一个节点的整体,所以指针类型必须和下一个节点类型相同 } *PNODE, NODE; PNODE init_list(); // 初始化链表 void add_list(PNODE pHead,int val); // 给链表追加节点 void traverse_list(PNODE pHead); // 遍历输出链表 bool is_empty(PNODE pHead); // 判断链表是否为空 int length_list(PNODE pHead); // 获取链表长度 void sort_list(PNODE pHead); // 对链表排序 // 这里我使用的是下标index(从0开始),注意不是pos(从1开始) bool insert_list(PNODE pHead,int index,int val);// 插入节点 bool delete_list(PNODE pHead,int index,int *val);// 删除节点 int main() { PNODE pHead = init_list(); int i; for(i = 0; i < 5; i++) { add_list(pHead, pow(2,i)); } traverse_list(pHead); if(is_empty(pHead)) { printf("链表为空\n"); } else { printf("链表不为空\n"); } printf("链表长度为:%d\n",length_list(pHead)); sort_list(pHead); traverse_list(pHead); insert_list(pHead,0,5); printf("插入成功:"); traverse_list(pHead); int val; delete_list(pHead, 5, &val); printf("删除的值为:%d\n", val); traverse_list(pHead); //pHead指向的内存是我在init_list函数中动态分配,执行完之后需要手动销毁 free(pHead); return 0; } PNODE init_list() { PNODE pHead = (PNODE) malloc(sizeof(NODE)); if(pHead == NULL) { printf("内存分配失败\n"); exit(-1); } pHead->pNext = NULL; return pHead; } void add_list(PNODE pHead,int val) { // 1.新建一个节点 PNODE pNew = (PNODE) malloc(sizeof(NODE)); if(pNew == NULL) { printf("内存分配失败\n"); exit(-1); } // 2.给新节点赋值 pNew->data = val; pNew->pNext = NULL; // 3.将pTail指向尾节点 PNODE pTail = pHead; while(pTail->pNext != NULL) { // 当pTail指向的节点不为NULL,说明pTail指向的不是尾节点 pTail = pTail->pNext; // 进入循环说明pTail指向的还不是尾节点,所以将pTail指向下一个节点 } // 4.最后将新建节点pNew挂载到尾节点之后 pTail->pNext = pNew; } void traverse_list(PNODE pHead) { // 1.创建一个指针(pMOVE),指向首节点(pHead->pNext) PNODE pMove = pHead->pNext; int i; // 2.如果pMove指向的节点不为空,则进入循环输出 while(pMove != NULL) { printf("%d ", pMove->data); //3.将 pMove 指向下一个节点 pMove = pMove->pNext; } printf("\n"); return; } bool is_empty(PNODE pHead) { if(pHead->pNext == NULL) { return true; } else { return false; } } int length_list(PNODE pHead) { PNODE pMove = pHead; int len = 0; while(pMove->pNext != NULL) { pMove = pMove->pNext; len++; } return len; } void sort_list(PNODE pHead) { //这里使用的是选择排序,与数组的选择排序有点不同,因为链表不能记录最小值的下标,所以每轮比较会进行多次交换 int i,j,t; int len = length_list(pHead); PNODE p, q; for(i = 0, p = pHead->pNext; i < len-1; i++) { for(j = i+1,q = p->pNext; j < len; j++, q = q->pNext) { if(p->data > q->data) { t = p->data; p->data = q->data; q->data = t; } } } return; } bool insert_list(PNODE pHead,int index,int val) { int i = 0; PNODE p = pHead; // 在下标index前插入节点,通过循环拿到下标index前面的节点,这样便于插入 while(p != NULL && i < index) { p = p->pNext; i++; } // 判断p是否指向 NULL,插入的下标位置index是否小于0 if(p == NULL || index < 0) {//老师这里用的是 i>pos所表达的意思就是 index<0,个人认为index<0更加便于理解 return false; } PNODE pNew = (PNODE) malloc(sizeof(NODE)); if(pNew == NULL) { printf("内存分配失败\n"); exit(-1); } pNew->pNext = p->pNext; pNew->data = val; p->pNext = pNew; return true; } bool delete_list(PNODE pHead,int index,int *val) { int i = 0; PNODE p = pHead; // 这里删除,也是通过循环拿到“需要删除节点的前一个节点 ” while(p->pNext != NULL && i < index) { p = p->pNext; i++; } if(NULL == p->pNext || index < 0){ return false; } *val = p->pNext->data; // 删除 p 后面第一个节点,并让 p 指向后面的第二个节点 PNODE q = p->pNext; // 判断后面的第二个节点是否存在,不存在直接赋值为NULL p->pNext = p->pNext->pNext == NULL ? NULL : p->pNext->pNext; free(q); q = NULL; return true; }