3.链表
3.1 链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的 。
现实中:
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
- 单向、双向
- 带头、不带头
- 循环、非循环
常见
1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结
构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向
循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而
简单了,后面我们代码实现了就知道了。
3.2链表的实现
// 1、无头单向非循环链表增删查改实现
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType _data;
struct SListNode* _next;
}SListNode;
typedef struct SList
{
SListNode* _head;
}SList;
void SListInit(SList* plist);
void SListDestory(SList* plist);
SListNode* BuySListNode(SLTDataType x);
void SListPushFront(SList* plist, SLTDataType x);
void SListPopFront(SList* plist);
SListNode* SListFind(SList* plist, SLTDataType x);
// 在pos的后面进行插入
void SListInsertAfter(SListNode* pos, SLTDataType x);
// 在pos的前面进行插入
void SListEraseAfter(SListNode* pos);
void SListRemove(SList* plist, SLTDataType x);
void SListPrint(SList* plist);
void TestSList();
// 2、带头双向循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
typedef struct List
{
ListNode* _head;
}List;
void ListInit(List* plist);
void ListDestory(List* plist);
void ListPushBack(List* plist, LTDataType x);
void ListPushBack(List* plist);
void ListPushFront(List* plist, LTDataType x);
void ListPopFront(List* plist);
ListNode* ListFind(List* plist, LTDataType x);
// 在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 删除pos位置的节点
void ListErase(ListNode* pos);
void ListRemove(List* plist, LTDataType x);
void ListPrint(List* plist);
4.顺序表和链表的区别和联系
顺序表:
优点:空间连续、支持随机访问
1.中间或前面部分的插入删除时间复杂度O(N)
2.增容的代价比较大。
链表:
缺点;以节点为单位存储,不支持随机访问
优点:1.任意位置插入删除时间复杂度为O(1)
2.没有增容问题,插入一个开辟一个空间。
接口实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include "Slist.h"
SlistNode* Slistbyroom(SlistType x)
{
SlistNode* node = malloc(sizeof(SlistNode));
node->Date = x;
node->next = NULL;
return node;
}
void Slistpopback(SlistNode** plist)
{
SlistNode* tail = *plist;
SlistNode* head = *plist;
if (*plist == NULL)
{
free(*plist);
}
while (tail->next!=NULL)
{
head = tail;
tail = tail->next;
}
free(tail);
head->next = NULL;
}
void Slistprint(SlistNode** plist)//打印
{
SlistNode* til = *plist;
while (til)
{
printf("%d->", til->Date);
til = til->next;
}
printf("NULL\n");
}
void SlistpopFront(SlistNode** plist)//头删
{
SlistNode* tail= *plist;
SlistNode* head = *plist;
if (*plist == NULL)
{
free(*plist);
}
else
{
tail = tail->next;
*plist = tail;
free(head);
}
}
void SlistpushFront(SlistNode** plist, SlistType x)//头插
{
SlistNode* newnode = Slistbyroom(x);
if (*plist == NULL)
{
*plist = newnode;
}
else
{
SlistNode* str = *plist;
*plist = newnode;
newnode->next = str;
}
}
void Slistpushback(SlistNode** plist, SlistType x)//尾插
{
SlistNode* newnode=Slistbyroom(x);
if (*plist==NULL)
{
*plist = newnode;
}
else
{
SlistNode* str = *plist;
while (str->next != NULL)
{
str = str->next;
}
str->next = newnode;
}
}