单链表专题(冲冲冲)(上):https://developer.aliyun.com/article/1624358
2.2.5节点的查找
Node* SLTFind(Node* phead, SLdatatype x) { Node* pcur = phead; while (pcur)//pcur!=NULL { if (pcur->data == x) { return pcur; } pcur = pcur->next; } //pcur==NULL; return NULL; }
2.2.6指定位置前后节点的插入
void SLTInsert(Node** pphead, Node* pos, SLdatatype x) { assert(pphead && *pphead); assert(pos); Node* newnode = SLTBuyNode(x); //pos==*pphead.说明是头插 if (pos == *pphead) { PushFront(pphead, x); } else { Node* prev = *pphead; while (prev->next != pos) { prev = prev->next; } newnode->next = pos; prev->next = newnode; } } void SLTInsertAfter(Node* pos, SLdatatype x) { assert(pos); Node* newnode = SLTBuyNode(x); newnode->next = pos->next; pos->next = newnode; }
2.2.7指定节点的删除
void SLTErase(Node** pphead, Node* pos) { assert(pphead && *pphead); assert(pos); //pos是头结点 if (pos == *pphead) { PopFront(pphead); } else { Node* prev = *pphead; while (prev->next != pos) { prev = prev->next; } prev->next = pos->next; free(pos); pos = NULL; } } //删除pos之后的节点 void SLTEraseAfter(Node* pos) { assert(pos && pos->next); Node* del = pos->next; pos->next = del->next; free(del); del = NULL; }
2.2.8链表的销毁
//链表的销毁(销毁一个一个的节点) void SListDesTroy(Node** pphead) { assert(pphead && *pphead); Node* pcur = *pphead; while (pcur) { Node* next = pcur->next; free(pcur); pcur = next; } *pphead = NULL; }
2.3代码测试
//#define _CRT_SECURE_NO_WARNINGS #include "SList.h" void test1() {//实验链表是否建立成功 Node*node1 = (Node*)malloc(sizeof(Node)); node1->data = 1; Node* node2 = (Node*)malloc(sizeof(Node)); node2->data = 2; Node* node3 = (Node*)malloc(sizeof(Node)); node3->data = 3; Node* node4 = (Node*)malloc(sizeof(Node)); node4->data = 4; //j将四个节点连接起来 node1->next = node2; node2->next = node3; node3->next = node4; node4->next = NULL; //定义一个头指针指向node1 Node* head = node1; SLTprint(head); } void test2() { Node* plist = NULL; //形参若引起实参的改变需要传址 PushBack(&plist, 1);//尾插 PushBack(&plist, 2); PushBack(&plist, 3); PushBack(&plist, 4); //PushBack(NULL, 4);--error SLTprint(plist); /* Node* ret = SLTFind(plist, 3); if (ret == NULL) { printf("not found!"); } else printf("找到了!\n"); Node* find = SLTFind(plist, 3); SLTInsert(&plist,find, 11);//指定位置插入 SLTprint(plist); PushFront(&plist, 6);//头插 PushFront(&plist, 8); PushFront(&plist, 9); SLTprint(plist); PopFront(&plist);//头删 SLTprint(plist); //PopBack(&plist); //SLTprint(plist); PopBack(&plist);//尾删 SLTprint(plist); PopFront(&plist); SLTprint(plist); PopFront(&plist); SLTprint(plist); //删除pos节点 Node* find1 = SLTFind(plist, 11); SLTErase(&plist, find1); SLTprint(plist); //在指定位置之后插⼊数据 SLTInsertAfter(find,12); SLTprint(plist); //删除pos之后的节点 SLTEraseAfter(find); SLTprint(plist); */ PopFront(&plist); SLTprint(plist); //SListDesTroy(&plist); //SLTprint(plist); } int main() { //test1(); test2(); return 0; }
根据自身情况可将注释符号去掉测试相应函数功能。
注意
对于2.2和2.3的代码运用都要引用定义好的头文件“Slist.h”
3.链表的分类(简要介绍)
后续小编会详细讲解
链表的结构非常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构。
虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构: 单链表和双向带头循环链表
1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结 构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。