目录
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的
1 链式结构在逻辑上是连续的, 但是在物理上不一定连续
2 现实中的结点一般都是从堆中申请出来的
3 从堆上申请的空间 是按照一定的策略来分配的 再次申请的空间可能连续 也可能不连续
链表的分类:
1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结 构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都 是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带 来很多优势,实现反而简单了,后面我们代码实现了就知道了
- #pragma once
- #include
- #include
- #include
-
-
- typedef int SLTDataType;
-
- typedef struct SListNode
- {
- SLTDataType data;
- struct SListNode* next;
- }SLTNode;
-
- //打印
- void SLTPrint(SLTNode* phead);
-
- //扩容
- SLTNode* BuySListNode(SLTDataType x);
-
- //尾插头插
- void SLTPushBack(SLTNode** pphead, SLTDataType x);
- void SLTPushFront(SLTNode** pphead, SLTDataType x);
-
- //尾删头删
- void SLTPopBack(SLTNode** pphead);
- void SLTPopFront(SLTNode** pphead);
-
- //找位置
- SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
-
- // 在pos之前插入x
- void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
-
- // 在pos以后插入x
- void SLTInsertAfter(SLTNode* pos, SLTDataType x);
-
- // 删除pos位置
- void SLTErase(SLTNode** pphead, SLTNode* pos);
-
- // 删除pos的后一个位置
- void SLTInsertAfter(SLTNode* pos);
-
- #include"SList.h"
-
- //打印
- void SLTPrint(SLTNode* phead)
- {
- SLTNode* cur = phead;
- while (cur)
- {
- printf("%d->", cur->data);
- cur = cur->next;
- }
- printf("NULL\n");
-
- }
-
- //扩容
- SLTNode* BuySListNode(SLTDataType x)
- {
- SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
- if (newnode == NULL)
- {
- perror("malloc failed");
- exit(-1);
- }
- newnode->data = x;
- newnode->next = NULL;
- return newnode;
- }
- //尾插
- void SLTPushBack(SLTNode** pphead, SLTDataType x)
- {
- SLTNode* newnode = BuySListNode(x);
- if (*pphead == NULL)
- {
- *pphead = newnode;
- }
- else
- {
- SLTNode* tail = *pphead;
- while (tail->next != NULL)
- {
- tail = tail->next;
- }
- tail->next = newnode;
- }
-
- }
总结:改变结构体用结构体指针 改变结构体二级指针
- //头插
- void SLTPushFront(SLTNode** pphead, SLTDataType x)
- {
- SLTNode* newnode = BuySListNode(x);
- newnode->next = *pphead;
- *pphead = newnode;
-
- }
- //尾删
- void SLTPopBack(SLTNode** pphead)
- {
- //空
- assert(*pphead);
-
- //一个节点
- if ((*pphead)->next == NULL)
- {
- free(*pphead);
- *pphead = NULL;
- }
-
-
- else
- {
- SLTNode* tail = *pphead;
- SLTNode* tailPrev = *pphead;
- while (tail->next)
- {
- tailPrev = tail;
- tail = tail->next;
- }
- free(tail);
- tailPrev->next = NULL;
- }
- }
- //头删
- void SLTPopFront(SLTNode** pphead)
- {
- assert(*pphead);
-
- SLTNode* newhead = (*pphead)->next;
- free(*pphead);
- *pphead = newhead;
-
- }
- // 在pos之前插入x
- void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
- {
- assert(*pphead);
- assert(pos);
- if (pos == 0)
- {
- SLTPushFront(*pphead, x);
- }
- else
- {
- SLTNode* newnode = BuySListNode(x);
- SLTNode* prev = *pphead;
- while (prev->next != pos)
- {
- prev = prev->next;
- }
- prev->next = newnode;
- newnode->next = pos;
- }
- }
- // 在pos以后插入x
- void SLTInsertAfter(SLTNode* pos, SLTDataType x)
- {
- assert(pos);
- SLTNode* newnode = BuySListNode(x);
- newnode->next = pos->next;
- pos->next = newnode;
-
- }
- // 删除pos位置
- void SLTErase(SLTNode** pphead, SLTNode* pos)
- {
- assert(*pphead);
- assert(pos);
- if (pos == *pphead)
- {
- SLTPopFront(pphead);
- }
- else
- {
- SLTNode* prev = *pphead;
- while (prev->next != pos)
- {
- prev = prev->next;
- }
- prev->next = pos->next;
- free(pos);
- }
- }
- // 删除pos的后一个位置
- void SLTEraseAfter(SLTNode* pos)
- {
- assert(pos);
- assert(pos->next);//检查pos是否是尾节点
- SLTNode* posNext = pos->next;
-
- pos->next = posNext->next;
- free(posNext);
- posNext = NULL;
- }
- //销毁
- void SLTDestroy(SLTNode** pphead)
- {
- assert(pphead);
- SLTNode* cur = *pphead;
- while (cur)
- {
- SLTNode* next = cur->next;
- free(cur);
- cur = next;
- }
- *pphead = NULL;
- }
- void TestSList5()
- {
- SLTNode* plist = NULL;
- SLTPushBack(&plist, 1);//传地址 才能改变结构体
- SLTPushBack(&plist, 2);
- SLTPushBack(&plist, 3);
- SLTPushBack(&plist, 4);
- SLTPushBack(&plist, 5);
- SLTPushBack(&plist, 6);
- SLTPrint(plist);
-
- SLTPushFront(&plist, 40);
- SLTPrint(plist);
-
- SLTPopBack(&plist);
- SLTPrint(plist);
-
- SLTPopFront(&plist);
- SLTPrint(plist);
-
- int x = 0;
- scanf("%d", &x);
- SLTNode* pos = SLTFind(plist, x);
-
- SLTInsertAfter(pos, 50);
- SLTInsert(&plist, pos, 40);
- SLTPrint(plist);
-
- SLTEraseAfter(pos);
- SLTPrint(plist);
-
- SLTErase(&plist, pos);
- SLTPrint(plist);
- }
- int main()
- {
- TestSList5();
- return 0;
- }