赞
踩
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表的结构可以形象的看作是一辆火车,每块空间独立存在并且通过指针链接在一起。
在数据结构中:
注意:1、从上图可以看出,链式结构在逻辑上是连续的,但在物理上不一定连续。
2、现实的节点一般都是从堆上申请出来的。
3、在堆上申请的空间是按一定策略来分配的,两次申请的空间可能连续也可能不连续。
实际上链表的结构非常多样,以下情况组合起来就有八种链表结构
1、单向或者双向
2、带头(哨兵位)或者不带头
3、循环或者非循环
虽然链表中存在这么多结构,但是在实际中最常用的就只有两种结构:
1、无头单向非循环链表:结构简单,一般不会单独用来存储数据,实际中更多的是作为其他数据结构的子结构,如哈希桶、图的邻接表等。
2、带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表,这个结构虽然结构较为复杂,但是使用代码实现反而因为结构的原因更加简单了,这一点在后续代码实现过程中会体现出来。
在代码实现过程中,我们依然为两个链表分别建立三个文件
无头单向非循环链表:SList.h(函数声明)、SList.c(函数定义)、4.c(测试函数功能)
带头双向循环链表:List.h(函数声明)、List.c(函数定义)、5.c(测试函数功能)
首先我们需要创建一个结构体,其中一个存放数据,另一个指向下一个空间。
- typedef int SLTDateType;
-
- typedef struct SListNode
- {
- SLTDateType data;
- struct SListNode* next;
- }SListNode;
尾插需要先判断链表是否为空,为空则直接建立一个节点就行,不为空则需要遍历到最后一个节点后插入
- // 单链表的尾插
- void SListPushBack(SListNode** pplist, SLTDateType x)
- {
- assert(pplist);
- assert(*pplist);
-
- SListNode* newnode = BuySListNode(x);
-
- if (*pplist == NULL)
- {
- *pplist = newnode;
- }
- else
- {
- SListNode* tail = *pplist;
- while (tail->next != NULL)
- {
- tail = tail->next;
- }
- tail->next = newnode;
- }
- }
头插的实现较为简单,只需要在链表头插入即可
- // 单链表的头插
- void SListPushFront(SListNode** pplist, SLTDateType x)
- {
- assert(pplist);
-
- SListNode* newnode = BuySListNode(x);
- newnode->next = *pplist;
- *pplist = newnode;
- }
测试结果
尾删和尾插的思路刚好相反,注意需要判空
- // 单链表的尾删
- void SListPopBack(SListNode** pplist)
- {
- assert(pplist);
- assert(*pplist);
-
- if ((*pplist)->next == NULL)
- {
- free(*pplist);
- *pplist = NULL;
- }
- else
- {
- SListNode* tail = *pplist;
- while (tail->next->next)
- {
- tail = tail->next;
- }
-
- free(tail->next);
- tail->next = NULL;
- }
- }
- // 单链表的头删
- void SListPopFront(SListNode** pplist)
- {
- assert(pplist);
- assert(*pplist);
-
- if ((*pplist)->next == NULL)
- {
- free(*pplist);
- *pplist = NULL;
- }
- else
- {
- SListNode* del = *pplist;
- *pplist = (*pplist)->next;
- free(del);
- }
- }
测试结果
- // 单链表查找
- SListNode* SListFind(SListNode* plist, SLTDateType x)
- {
- SListNode* cur = plist;
- while (cur)
- {
- if (cur->data == x)
- {
- return cur;
- }
- cur = cur->next;
- }
- return NULL;
- }
这里我们依然创建一个结构体,其中一个存放数据,另外两个分别指向前一片空间和后一片空间
- typedef int LTDataType;
-
- typedef struct ListNode
- {
- LTDataType _data;
- struct ListNode* _next;
- struct ListNode* _prev;
- }ListNode;
创建哨兵位时只有这一个元素,该元素的前后指针都指向自己,已到达循环的目的
- // 创建头结点(哨兵位)
- ListNode* ListCreate()
- {
- ListNode* pHead = BuyNode(-1);
- pHead->_next = pHead;
- pHead->_prev = pHead;
- return pHead;
- }
- // 双链表的尾插
- void ListPushBack(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* tail = pHead->_prev;
- ListNode* newnode = BuyNode(x);
-
- tail->_next = newnode;
- newnode->_prev = tail;
- newnode->_next = pHead;
- pHead->_prev = newnode;
- }
- // 双链表的头插
- void ListPushFront(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* newnode = BuyNode(x);
- ListNode* first = pHead->_next;
-
- pHead->_next = newnode;
- newnode->_prev = pHead;
- newnode->_next = first;
- first->_prev = newnode;
- }
测试结果
- // 双链表的尾删
- void ListPopBack(ListNode* pHead)
- {
- assert(pHead);
-
- ListNode* tail = pHead->_prev;
- ListNode* tailprev = tail->_prev;
- free(tail);
- tailprev->_next = pHead;
- pHead->_prev = tailprev;
- }
- // 双链表的头删
- void ListPopFront(ListNode* pHead)
- {
- assert(pHead);
-
- ListNode* first = pHead->_next;
- ListNode* second = first->_next;
-
- pHead->_next = second;
- second->_prev = pHead;
- free(first);
- }
测试结果
- // 双链表的查找
- ListNode* ListFind(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* cur = pHead->_next;
- while (cur != pHead)
- {
- if (cur->_data == x)
- {
- return cur;
- }
- cur = cur->_next;
- }
- return NULL;
- }
- // 在pos位置的前面插入
- void ListInsert(ListNode* pos, LTDataType x)
- {
- assert(pos);
-
- ListNode* prev = pos->_prev;
- ListNode* newnode = BuyNode(x);
-
- prev->_next = newnode;
- newnode->_prev = prev;
- newnode->_next = pos;
- pos->_prev = newnode;
- }
- // 删除pos位置的节点
- void ListErase(ListNode* pos)
- {
- assert(pos);
-
- ListNode* posprev = pos->_prev;
- ListNode* posnext = pos->_next;
-
- posprev->_next = posnext;
- posnext->_prev = posprev;
- free(pos);
- }
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
-
-
-
- typedef int SLTDateType;
- typedef struct SListNode
- {
- SLTDateType data;
- struct SListNode* next;
- }SListNode;
-
- // 动态申请一个节点
- SListNode* BuySListNode(SLTDateType x);
- // 单链表打印
- void SListPrint(SListNode* plist);
- // 单链表尾插
- void SListPushBack(SListNode** pplist, SLTDateType x);
- // 单链表的头插
- void SListPushFront(SListNode** pplist, SLTDateType x);
- // 单链表的尾删
- void SListPopBack(SListNode** pplist);
- // 单链表头删
- void SListPopFront(SListNode** pplist);
- // 单链表查找
- SListNode* SListFind(SListNode* plist, SLTDateType x);
- #include"SList.h"
-
- SListNode* BuySListNode(SLTDateType x)
- {
- SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- return;
- }
- newnode->data = x;
- newnode->next = NULL;
-
- return newnode;
- }
-
-
- void SListPrint(SListNode* plist)
- {
- SListNode* cur = plist;
- while (cur != NULL)
- {
- printf("%d->", cur->data);
- cur = cur->next;
- }
- printf("NULL\n");
- }
-
-
- void SListPushBack(SListNode** pplist, SLTDateType x)
- {
- assert(pplist);
- assert(*pplist);
-
- SListNode* newnode = BuySListNode(x);
-
- if (*pplist == NULL)
- {
- *pplist = newnode;
- }
- else
- {
- SListNode* tail = *pplist;
- while (tail->next != NULL)
- {
- tail = tail->next;
- }
- tail->next = newnode;
- }
- }
-
- void SListPushFront(SListNode** pplist, SLTDateType x)
- {
- assert(pplist);
-
- SListNode* newnode = BuySListNode(x);
- newnode->next = *pplist;
- *pplist = newnode;
- }
-
- void SListPopBack(SListNode** pplist)
- {
- assert(pplist);
- assert(*pplist);
-
- if ((*pplist)->next == NULL)
- {
- free(*pplist);
- *pplist = NULL;
- }
- else
- {
- SListNode* tail = *pplist;
- while (tail->next->next)
- {
- tail = tail->next;
- }
-
- free(tail->next);
- tail->next = NULL;
- }
- }
-
- void SListPopFront(SListNode** pplist)
- {
- assert(pplist);
- assert(*pplist);
-
- if ((*pplist)->next == NULL)
- {
- free(*pplist);
- *pplist = NULL;
- }
- else
- {
- SListNode* del = *pplist;
- *pplist = (*pplist)->next;
- free(del);
- }
- }
-
- SListNode* SListFind(SListNode* plist, SLTDateType x)
- {
- SListNode* cur = plist;
- while (cur)
- {
- if (cur->data == x)
- {
- return cur;
- }
- cur = cur->next;
- }
- return NULL;
- }
- #include"SList.h"
-
-
- void TestSList1()
- {
- SListNode* plist = NULL;
- SListPushFront(&plist, 1);
- SListPushFront(&plist, 2);
- SListPushFront(&plist, 3);
- SListPushFront(&plist, 4);
-
- SListPrint(plist);
-
- SListPushBack(&plist, 5);
- SListPushBack(&plist, 6);
- SListPushBack(&plist, 7);
- SListPushBack(&plist, 8);
-
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPopBack(&plist);
- SListPopBack(&plist);
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPrint(plist);
-
- SListPopBack(&plist);
- SListPrint(plist);
-
- /*SListPopBack(&plist);
- SListPrint(plist);*/
-
- /*SListPopFront(&plist);
- SListPrint(plist);
-
- SListPopFront(&plist);
- SListPrint(plist);
-
- SListPopFront(&plist);
- SListPrint(plist);
-
- SListPopFront(&plist);
- SListPrint(plist);
-
- SListPopFront(&plist);
- SListPrint(plist);*/
-
- }
-
-
-
- int main()
- {
- TestSList1();
-
- return 0;
- }
- #include<stdio.h>
- #include<assert.h>
- #include<stdlib.h>
- #include<stdbool.h>
-
-
- typedef int LTDataType;
- typedef struct ListNode
- {
- LTDataType _data;
- struct ListNode* _next;
- struct ListNode* _prev;
- }ListNode;
-
- // 创建返回链表的头结点.
- ListNode* ListCreate();
- // 双向链表销毁
- void ListDestory(ListNode* pHead);
- // 双向链表打印
- void ListPrint(ListNode* pHead);
- // 双向链表尾插
- void ListPushBack(ListNode* pHead, LTDataType x);
- // 双向链表尾删
- void ListPopBack(ListNode* pHead);
- // 双向链表头插
- void ListPushFront(ListNode* pHead, LTDataType x);
- // 双向链表头删
- void ListPopFront(ListNode* pHead);
- // 双向链表查找
- ListNode* ListFind(ListNode* pHead, LTDataType x);
- // 双向链表在pos的前面进行插入
- void ListInsert(ListNode* pos, LTDataType x);
- // 双向链表删除pos位置的节点
- void ListErase(ListNode* pos);
- #include"List.h"
-
-
- ListNode* BuyNode(LTDataType x)
- {
- ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- return NULL;
- }
-
- newnode->_data = x;
- newnode->_next = NULL;
- newnode->_prev = NULL;
- }
-
- ListNode* ListCreate()
- {
- ListNode* pHead = BuyNode(-1);
- pHead->_next = pHead;
- pHead->_prev = pHead;
- return pHead;
- }
-
- void ListPrint(ListNode* pHead)
- {
- assert(pHead);
-
- printf("sentinel<==>");
- ListNode* cur = pHead->_next;
- while (cur != pHead)
- {
- printf("%d<==>", cur->_data);
- cur = cur->_next;
- }
- printf("\n");
- }
-
- bool LTEmpty(ListNode* pHead)
- {
- assert(pHead);
-
- return pHead->_next == pHead;
- }
-
- void ListPushBack(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* tail = pHead->_prev;
- ListNode* newnode = BuyNode(x);
-
- tail->_next = newnode;
- newnode->_prev = tail;
- newnode->_next = pHead;
- pHead->_prev = newnode;
- }
-
- void ListPopBack(ListNode* pHead)
- {
- assert(pHead);
-
- ListNode* tail = pHead->_prev;
- ListNode* tailprev = tail->_prev;
- free(tail);
- tailprev->_next = pHead;
- pHead->_prev = tailprev;
- }
-
- void ListPushFront(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* newnode = BuyNode(x);
- ListNode* first = pHead->_next;
-
- pHead->_next = newnode;
- newnode->_prev = pHead;
- newnode->_next = first;
- first->_prev = newnode;
- }
-
- void ListPopFront(ListNode* pHead)
- {
- assert(pHead);
-
- ListNode* first = pHead->_next;
- ListNode* second = first->_next;
-
- pHead->_next = second;
- second->_prev = pHead;
- free(first);
- }
-
- ListNode* ListFind(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- ListNode* cur = pHead->_next;
- while (cur != pHead)
- {
- if (cur->_data == x)
- {
- return cur;
- }
- cur = cur->_next;
- }
- return NULL;
- }
-
- void ListInsert(ListNode* pos, LTDataType x)
- {
- assert(pos);
-
- ListNode* prev = pos->_prev;
- ListNode* newnode = BuyNode(x);
-
- prev->_next = newnode;
- newnode->_prev = prev;
- newnode->_next = pos;
- pos->_prev = newnode;
- }
-
- void ListErase(ListNode* pos)
- {
- assert(pos);
-
- ListNode* posprev = pos->_prev;
- ListNode* posnext = pos->_next;
-
- posprev->_next = posnext;
- posnext->_prev = posprev;
- free(pos);
- }
-
- void ListDestory(ListNode* pHead)
- {
- assert(pHead);
-
- ListNode* cur = pHead->_next;
- while (cur != pHead)
- {
- ListNode* next = cur->_next;
- free(cur);
- cur = next;
- }
- free(pHead);
- }
- #include"List.h"
-
- TestList()
- {
- ListNode* plist = ListCreate();
- ListPushBack(plist, 1);
- ListPushBack(plist, 2);
- ListPushBack(plist, 3);
- ListPushBack(plist, 4);
- ListPrint(plist);
-
- ListPushFront(plist, 5);
- ListPushFront(plist, 6);
- ListPushFront(plist, 7);
- ListPushFront(plist, 8);
- ListPrint(plist);
-
- ListPopBack(plist);
- ListPopBack(plist);
- ListPopBack(plist);
- ListPrint(plist);
-
- ListPopFront(plist);
- ListPopFront(plist);
- ListPopFront(plist);
- ListPrint(plist);
-
- }
-
- int main()
- {
- TestList();
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。