赞
踩
前言
为了解决顺序表存在的一些问题,我们引入了单链表~
创造不易,可以点点赞吗~
如有错误,欢迎指出~
目录
而链表可以规避这些问题~
链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
- typedef int SLTDataTpye;
-
- //链表由节点组成
- typedef struct SListNode
- {
- SLTDataTpye data;//存储当前节点的数据
- SLTNode* next;//存储下一节点的地址
- }SLTNode;//将该链表命名为SLTNode
-
- //typedef struct SListNode SLTNode;
- #pragma once
- #define _CRT_SECURE_NO_WARNINGS
- #include<stdlib.h>
- #include<stdio.h>
- #include<assert.h>
-
- typedef int SLTData;
- typedef struct SListNode SLTNode;
-
- //定义节点
- struct SListNode {
- SLTData data;
- struct SListNode* next;
- };
-
- //打印链表
- void SLTPrint(SLTNode* phead);
-
- //销毁链表
- void SLTDesTroy(SLTNode** pphead);

- #include"SList.h"
-
- //打印链表
- void SLTPrint(SLTNode* phead)
- {
- //用pcur遍历链表
- SLTNode* pcur = phead;
- while (pcur)
- {
- printf("%d->", pcur->data);
- pcur = pcur->next;
- }
- printf("NULL\n");
- }
-
- //销毁链表
- void SLTDesTroy(SLTNode** pphead)
- {
- assert(pphead);
- assert(*pphead);
-
- SLTNode* pcur = *pphead;
- //循环删除节点
- while (pcur)
- {
- SLTNode* next = pcur->next;//创建next节点保存pcur下一个节点
- free(pcur);
- pcur = next;
- }
- *pphead = NULL;
- }

- #include"SList.h"
-
- void SListTest01()
- {
- //对第一个节点申请了空间
- SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
- node1->data = 1;
- SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
- node2->data = 2;
- SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
- node3->data = 3;
- SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
- node4->data = 4;
-
- //将节点连接在一起
- node1->next = node2;
- node2->next = node3;
- node3->next = node4;
- node4->next = NULL;
-
- //创建链表plist
- SLTNode* plist = node1;//plist指针保存了第一个节点的地址
- SLTPrint(plist);
- }
-
- int main()
- {
- SListTest01();
- return 0;
- }

尾插
头插
指针关系
- //申请一个新节点的方法
- SLTNode* SLTBuyNode(SLTDataType x)
- {
- SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
- newnode->data = x;
- newnode->next = NULL;
- return newnode;
- }
-
- //链表的头插和尾插
- //尾插
- void SLTPushBack(SLTNode** pphead, SLTDataType x)//链表头节点的地址和要插入的数据
- {
- //排查空指针
- assert(pphead);
- SLTNode* newnode = SLTBuyNode(x);
-
- //链表为空,新节点作为phead
- if (*pphead == NULL)
- {
- *pphead = newnode;
- return;
- }
- //链表不为空,找尾节点
- SLTNode* ptail = *pphead;
- while (ptail->next)
- {
- ptail = ptail->next;
- }
- //此时ptail就是尾节点
- ptail->next = newnode;
- }
- //头插
- void SLTPushFront(SLTNode** pphead, SLTDataType x)
- {
- assert(pphead);
- SLTNode* newnode = SLTBuyNode(x);
-
- newnode->next = *pphead;
- *pphead = newnode;
- }

- //链表的头删和尾删
- //尾删
- void SLTPopBack(SLTNode** pphead)
- {
- assert(pphead);
- //链表不能为空
- assert(*pphead);
-
- //只有一个节点
- if ((*pphead)->next == NULL)
- {
- free(*pphead);
- *pphead = NULL;
- return;
- }
- //有多个节点
- SLTNode* ptail = *pphead;
- SLTNode* prev = NULL;
- //让ptail走到尾节点
- while (ptail->next)
- {
- prev = ptail;
- ptail = ptail->next;
- }
- //销毁尾节点
- prev->next = NULL;
- free(ptail);
- ptail = NULL;
- }
-
- //头删
- void SLTPopFront(SLTNode** pphead)
- {
- assert(pphead);
- //链表不能为空
- assert(*pphead);
-
- //让第二个节点成为新的头
- SLTNode* next = (*pphead)->next;
- //把旧节点释放掉
- free(*pphead);
- *pphead = next;
- }

- //查找
- SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
- {
- assert(pphead);
-
- //遍历链表
- SLTNode* pcur = *pphead;
- while (pcur)
- {
- if (pcur->data == x)
- {
- return pcur;
- }
- pcur = pcur->next;
- }
- //没有找到
- return NULL;
- }

指定位置之前
指定位置之后
- //在指定位置之前插入数据
- void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
- {
- assert(pphead);
- assert(pos);
- //要加上链表不能为空
- assert(*pphead);
-
- SLTNode* newnode = SLTBuyNode(x);
- //pos刚好是头节点
- if (pos == *pphead)
- {
- //执行头插操作
- SLTPushFront(pphead, x);
- return;
- }
- //pos不是头节点的情况
- SLTNode* prev = *pphead;
- while (prev->next != pos)
- {
- prev = prev->next;
- }
- //将prev newnode pos 3者连接起来
- prev->next = newnode;
- newnode->next = pos;
-
- }
-
- //在指定位置之后插入数据
- void SLTInsertAfert(SLTNode* pos, SLTDataType x)
- {
- assert(pos);
- SLTNode* newnode = SLTBuyNode(x);
- newnode->next = pos->next;
- pos->next = newnode;
- }

删除指定位置数据
删除指定位置之后
- //删除pos节点
- void SLTErase(SLTNode** pphead, SLTNode* pos)
- {
- assert(pphead);
- assert(*pphead);
- assert(pos);
-
- //pos刚好是头节点时,没有前驱节点,执行头删
- if (*pphead == pos)
- {
- //头删
- SLTPopFront(pphead);
- return;
- }
- //头节点没有前驱节点,所以要排除以上情况
- SLTNode* prev = *pphead;
- while (prev->next != pos)
- {
- prev = prev->next;
- }
- prev->next = pos->next;
- free(pos);
- pos = NULL;
- }
-
- //删除pos之后的节点
- void SLTEraseAfter(SLTNode* pos)
- {
- assert(pos);
- //pos->next是最后一个节点
- assert(pos->next);
- //先pos指向pos->next->next
- //再将pos->next释放
- //其中要先保存要删除的节点
- SLTNode* del = pos->next;
- pos->next = pos->next->next;
- free(del);
- del = NULL;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。