已解决
2.C语言--链表-头插、头删、尾插、尾删、查找、插入和删除
来自网友在路上 172872提问 提问时间:2023-11-20 04:27:43阅读次数: 72
最佳答案 问答题库728位专家为你答疑解惑
文章目录
- 简介
- 动态顺序表结构体
- 1.头插功能
- 2.头删功能
- 3.尾插功能
- 4.尾删功能
- 5.查找功能
- 6.插入功能
- 6.1 指定位置之(前)去插入一个节点
- 6.2 指定位置之(后)去插入一个节点
- 7.删除功能
- 7.1 删除指定位置的数据-时间复杂度O(N)
- 7.2 删除指定位置后一个位置的数据-时间复杂度O(1)
- 8. 释放链表缓存
- 9. 打印链表的值
- 10.此程序共包含3个文件,2个.c文件和1个.h文件
- 10.1 SList.h文件
- 10.2 SList.c文件
- 10.3 test.c文件
简介
本文主要介绍链表的头插、头删、尾插、尾删、查找、插入和删除,提供全部的.c和.h文件,确保使用者直接复制粘贴到编译器上即可直接运行程序。
动态顺序表结构体
typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SLTNode;
1.头插功能
思路是将节点的首地址赋值到新申请节点的next中。
/*插入数据-头插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = *ppHead;*ppHead = newNode;return;
}
开辟一个新的节点,并将要插入的值放心节点对应的data中。
/*创建节点*/
SLTNode* CreatListNode(SLTDateType x)
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (NULL == newNode){printf("CreatListNode malloc fail\n");exit(-1);}newNode->data = x;newNode->next = NULL;return newNode;
}
2.头删功能
思路是将下一个节点的地址赋值到头节点地址上,将当前节点free掉。
/*头删*/
void SListPopFront(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* next = (*ppHead)->next;free(*ppHead);*ppHead = next;return;
}
3.尾插功能
思路是先检查输入*ppHead是否为空,不为空就找到链表的尾节点进行新节点的插入。
/*插入数据-尾插*/
void SListPushBack(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);/*新结点申请空间*/SLTNode* newNode = CreatListNode(x);if (*ppHead == NULL){*ppHead = newNode;}else{/*找到尾结点*/SLTNode* tail = *ppHead;while (tail->next != NULL){tail = tail->next;}tail->next = newNode;}return;
}
4.尾删功能
思路是释放节点时,要将下一个节点的地址保存好再释放当前节点。
/*尾删*/
void SListPopBack(SLTNode** ppHead)
{assert(ppHead != NULL);/*如果只有一个节点时,直接释放此节点*/if ((*ppHead)->next == NULL){free(*ppHead);*ppHead = NULL;}else/*存在2个及2个以上节点的处理方式*/{SLTNode* tail = *ppHead;SLTNode* pre = NULL;while (tail->next != NULL){pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}return;
}
5.查找功能
思路是遍历,找到节点后返回当前节点的地址,找不到就返回NULL。
/*查找*/
SLTNode* SListFind(SLTNode* pHead, SLTDateType x)
{assert(pHead != NULL);SLTNode* cur = pHead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}
6.插入功能
6.1 指定位置之(前)去插入一个节点
此方法是比较笨的方法,为了节约资源应该将数据往指定位置的后边插入。
/*指定位置插入数据-在pos位置之前去插入一个节点--时间复杂度O(N)*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x)
{assert(ppHead != NULL);assert(pos != NULL);SLTNode* newNode = CreatListNode(x);if (*ppHead == pos)/*pos的位置在第一个位置时*/{newNode->next = *ppHead;*ppHead = newNode;}else{/*找到pos位置的前一个位置*/SLTNode* posPrev = *ppHead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newNode;newNode->next = pos;}return NULL;
}
6.2 指定位置之(后)去插入一个节点
此方法是常用的插入方式,时间复杂度是O(1)。
/*指定位置插入数据-在pos位置之后去插入一个节点--时间复杂度O(1)*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = pos->next;pos->next = newNode;return NULL;
}
7.删除功能
7.1 删除指定位置的数据-时间复杂度O(N)
此方法需要记住当前节点前一个的节点地址,会多耗费时间资源,时间复杂度O(N)。
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos)
{assert(ppHead != NULL);assert(pos != NULL);/*如果删除的数据是头*/if (*ppHead == pos){SListPopFront(ppHead);}else{SLTNode* prev = *ppHead;while (prev->next != pos)/*找到pos前一个节点*/{prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}return NULL;
}
7.2 删除指定位置后一个位置的数据-时间复杂度O(1)
此方法需要记住当前节点前一个的节点地址,会多耗费时间资源,时间复杂度O(1)。
/*删除指定位置后一个位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos)
{assert(pos->next != NULL);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;return NULL;
}
8. 释放链表缓存
思路将下一个节点的地址先记住,然后释放当前节点。再将保存的地址赋值到当前节点循环释放缓存。
/*释放链表缓存*/
SLTNode* SListDestory(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* cur = *ppHead;while (cur){SLTNode* next = cur->next;free(cur);cur = next;}*ppHead = NULL;return NULL;
}
9. 打印链表的值
/*打印链表的值*/
void SListTPrint(SLTNode* pHead)
{SLTNode* cur = pHead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}return;
}
10.此程序共包含3个文件,2个.c文件和1个.h文件
10.1 SList.h文件
文件中包含了函数功能的头文件以及对应的结构体。
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SLTNode;void SListTPrint(SLTNode *pHead); /*打印链表的值*/
void SListPushBack(SLTNode** ppHead, SLTDateType x); /*插入数据-尾插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x); /*插入数据-头插*/void SListPopBack(SLTNode** ppHead); /*尾删*/
void SListPopFront(SLTNode** ppHead); /*头删*/SLTNode* SListFind(SLTNode* pHead, SLTDateType x); /*查找*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x);/*指定位置插入数据-在pos位置之前去插入一个节点*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x); /*指定位置插入数据-在pos位置之后去插入一个节点*/
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos); /*删除指定位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos); /*删除指定位置后一个位置的数据*/
SLTNode* SListDestory(SLTNode** ppHead); /*释放链表缓存*/SLTNode* CreatListNode(SLTDateType x); /*创建一个新的节点*/
10.2 SList.c文件
文件中包含了功能函数的具体实现方式。
#define _CRT_SECURE_NO_WARNINGS
#include "SList.h"/*插入数据-尾插*/
void SListPushBack(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);/*新结点申请空间*/SLTNode* newNode = CreatListNode(x);if (*ppHead == NULL){*ppHead = newNode;}else{/*找到尾结点*/SLTNode* tail = *ppHead;while (tail->next != NULL){tail = tail->next;}tail->next = newNode;}return;
}/*插入数据-头插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = *ppHead;*ppHead = newNode;return;
}/*创建节点*/
SLTNode* CreatListNode(SLTDateType x)
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (NULL == newNode){printf("CreatListNode malloc fail\n");exit(-1);}newNode->data = x;newNode->next = NULL;return newNode;
}/*尾删*/
void SListPopBack(SLTNode** ppHead)
{assert(ppHead != NULL);/*如果只有一个节点时,直接释放此节点*/if ((*ppHead)->next == NULL){free(*ppHead);*ppHead = NULL;}else/*存在2个及2个以上节点的处理方式*/{SLTNode* tail = *ppHead;SLTNode* pre = NULL;while (tail->next != NULL){pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}return;
}/*头删*/
void SListPopFront(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* next = (*ppHead)->next;free(*ppHead);*ppHead = next;return;
}/*查找*/
SLTNode* SListFind(SLTNode* pHead, SLTDateType x)
{assert(pHead != NULL);SLTNode* cur = pHead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}/*指定位置插入数据-在pos位置之前去插入一个节点--时间复杂度O(N)*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x)
{assert(ppHead != NULL);assert(pos != NULL);SLTNode* newNode = CreatListNode(x);if (*ppHead == pos)/*pos的位置在第一个位置时*/{newNode->next = *ppHead;*ppHead = newNode;}else{/*找到pos位置的前一个位置*/SLTNode* posPrev = *ppHead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newNode;newNode->next = pos;}return NULL;
}/*指定位置插入数据-在pos位置之后去插入一个节点--时间复杂度O(1)*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = pos->next;pos->next = newNode;return NULL;
}/*删除指定位置的数据--时间复杂度O(N)*/
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos)
{assert(ppHead != NULL);assert(pos != NULL);/*如果删除的数据是头*/if (*ppHead == pos){SListPopFront(ppHead);}else{SLTNode* prev = *ppHead;while (prev->next != pos)/*找到pos前一个节点*/{prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}return NULL;
}/*删除指定位置后一个位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos)
{assert(pos->next != NULL);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;return NULL;
}/*释放链表缓存*/
SLTNode* SListDestory(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* cur = *ppHead;while (cur){SLTNode* next = cur->next;free(cur);cur = next;}*ppHead = NULL;return NULL;
}/*打印链表的值*/
void SListTPrint(SLTNode* pHead)
{SLTNode* cur = pHead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}return;
}
10.3 test.c文件
用来进行相应功能的测试,分别测试尾插、尾删和头插、头删等功能。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "SList.h"void Test1()
{SLTNode* SList = NULL;/*尾插*/SListPushBack(&SList, 1);SListPushBack(&SList, 2);SListPushBack(&SList, 3);SListPushBack(&SList, 4);/*尾删*/SListPopBack(&SList);/*打印链表*/SListTPrint(SList);printf("NULL\n");return;
}void Test2()
{SLTNode* SList = NULL;/*头插*/SListPushFront(&SList, 1);SListPushFront(&SList, 2);SListPushFront(&SList, 3);/*头删*/SListPopFront(&SList);/*打印*/SListTPrint(SList);printf("NULL");return;
}void Test3()
{SLTNode* SList = NULL;SLTNode* pos = NULL;int i = 1;/*尾插*/SListPushBack(&SList, 1);SListPushBack(&SList, 5);SListPushBack(&SList, 2);SListPushBack(&SList, 3);SListPushBack(&SList, 2);/*查找数字的位置*/pos = SListFind(SList, 2);while (pos)/*查找到数据为2的节点的地址*/{printf("第%d个pos节点的:%p->%d\n", i++, pos->next, pos->data);if (pos->next){pos = SListFind(pos->next, 2);}else/*为空指针时,直接跳出循环*/{break;}}/*改变对应节点位置的数据,将5位置前边的位置添加个20*/pos = SListFind(SList, 5);if (pos)/*在5的位置之前插入20*/{SListInsert(&SList, pos, 20);}pos = SListFind(SList, 5);if (pos)/*在5的位置之后插入100*/{SListInsertAfter(pos, 100);}/*打印*/SListTPrint(SList);printf("NULL");return;
}int main()
{Test1();/*尾插+尾删*///Test2();/*头插+头删*///Test3(); /*指定位置前插入、后插入、寻找指定数据节点的位置*/return 0;
}
这里代码大家可以自己拷贝到VS编译器中,Test1(),Test2(),Test3(),分别打开注释看一下效果,本人亲测过,可以直接运行出结果的。
查看全文
99%的人还看了
相似问题
- 〖大前端 - 基础入门三大核心之JS篇㊲〗- DOM改变元素节点的css样式、HTML属性
- Java 算法篇-链表的经典算法:判断回文链表、判断环链表与寻找环入口节点(“龟兔赛跑“算法实现)
- 代码随想录二刷 | 链表 | 删除链表的倒数第N个节点
- 节点导纳矩阵
- bhosts 显示节点 “unreach“ 状态
- 电子电器架构 —— 车载网关边缘节点总线转换
- 〖大前端 - 基础入门三大核心之JS篇㊳〗- DOM访问元素节点
- 第四天||24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II
- CS224W5.1——消息传递和节点分类
- Vue报错解决Error in v-on handler: “Error: 无效的节点选择器:#div1“
猜你感兴趣
版权申明
本文"2.C语言--链表-头插、头删、尾插、尾删、查找、插入和删除":http://eshow365.cn/6-39989-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!