主页 > 电脑硬件  > 

单链表的概念,结构和优缺点

单链表的概念,结构和优缺点

1. 概念

链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

2. 单链表的结构

单链表是由一系列节点组成的线性结构,每个结点包含两个域。:数据域和指针域。

数据域用来存储数据,指针域用来存储下一个结点的指针。单链表的头结点指向第一个结点,最后一个结点的指针域为空。

一个结点的结构:

逻辑结构:为了方便形象理解,想象出来的。

物理结构:实际内存中,真实的样子。

1.3 单链表的优缺点

优点:

1. 插入和删除操作效率高(只需修改指针的指向)

2. 空间利用率高(不需要预先分配空间)

3. 长度可变

缺点:

1. 随机访问效率低(只能挨个遍历)

2. 存储空间浪费(每个结点包含数据和指针)

3. 链接信息的丢失 (无法访问前一个节点)

2. 单链表的实现

单链表各接口函数

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int SLTDataType;//这样做的目的是为了增加代码的可读性和可维护性,以及提高代码的可移植性, //因为如果将来需要更改 SLTDataType 的类型,只需要在 typedef 语句中修改一处即可, // 如果我们在程序的其他地方需要修改 SLTDataType 的类型, //只需在 typedef 语句中修改 int 为其他类型即可,不需要修改其他代码。 //typedef int SLTADataType; typedef struct SListNode //--single Linked List { SLTDataType data;//成员变量 struct SListNode* next; }SLTNode; void SLTPrint(SLTNode* phead); void SLPushFront(SLTNode** pphead, SLTDataType x);//头部插入 void SLPushBack(SLTNode** pphead, SLTDataType x);//尾部插入 void SLPopFront(SLTNode** pphead);//头部删除 void SLPopBack(SLTNode** pphead);//尾部删除 //单链表查找 SLTNode* STFind(SLTNode* phead, SLTDataType x); //单链表pos之前插入 void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); //单链表pos之后插入 void SLInsertAfter(SLTNode* pos, SLTDataType x); //单链表pos位置删除 void SLErase(SLTNode** pphead, SLTNode* pos); //单链表pos之后删除 void SLEraseAfter(SLTNode* phead);

2.1 结点的定义

单链表的英文为:Single linked list --简写为SL

而顺序表的英文是:Sequence table -- 简写为Seq

结点的英文为:node

typedef int SLTDataType; typedef struct SListNode //--single Linked List { SLTDataType data;//成员变量 struct SListNode* next; }SLTNode;

2.2 链表的打印

//函数的作用是遍历单链表,并将每个节点的数据元素打印到屏幕上。 void SLTPrint(SLTNode* phead)//参数是一个指向 SLTNode 类型的指针 phead,表示单链表的头节点。 { SLTNode* cur = phead;//头结点存储的地址给cur指针。 while (cur != NULL)//使用一个while循环对单链表进行遍历,循环条件为 cur 不为 NULL。 { printf("%d->", cur->data); cur = cur->next; } printf("NULL\n"); }

2.3 创建一个新节点

SLTNode* BuyLTNode(SLTDataType x)//表示要创建的节点的数据元素。 //函数的作用是创建一个新的单链表节点,并将其初始化为包含数据元素 x 的节点。 { SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode)); if (newnode == NULL) { perror("malloc fail"); return NULL; } newnode->data = x; newnode->next = NULL; return newnode;//返回的是一个结点的地址 }

2.4 单链表尾插

void SLPushBack(SLTNode** pphead, SLTDataType x)//尾插的本质是让上一个结点链接下一个结点 { SLTNode* newnode = BuyLTNode(x); // 1、空链表 // 2、非空链表 if (*pphead == NULL) { *pphead = newnode; } else { SLTNode* tail = *pphead; while (tail->next != NULL) { tail = tail->next; } tail->next = newnode; } }

2.5 单链表头插

void SLPushFront(SLTNode** pphead, SLTDataType x) { SLTNode* newnode = BuyLTNode(x); newnode->next = *pphead; *pphead = newnode; }

2.6 单链表头删

void SPopFront(SLTNode** pphead) { //没有节点 //暴力检查 assert(*pphead); if ((*pphead)->next == NULL) { free(*pphead); *pphead = NULL; } //多个节点 else { SLTNode* del = *pphead;//相当于一个标记,删掉的标记 //写法一 //*pphead = del->next; //写法二 *pphead = (*pphead)->next; free(del); } }

2.7 单链表尾删

void SLPopBack(SLTNode** pphead) { //没有节点(空链表) //暴力检查 assert(*pphead); //一个节点 if ((*pphead)->next == NULL) { free(*pphead); *pphead = NULL; }//多个节点 else { SLTNode* prev = NULL; SLTNode* tail = *pphead; //找尾 //方法一 /*while (tail->next) { prev = tail; tail = tail->next; } free(tail); prev->next = NULL;*/ //方法二 SLTNode* tail = *pphead; while (tail->next->next) { tail = tail->next; } free(tail->next); tail->next = NULL; } }

2.8 单链表查找/修改某个值

SLTNode* STFind(SLTNode* phead, SLTDataType x) { //assert(phead); SLTNode* cur = phead; while (cur) { if (cur->data == x) { return cur; } cur = cur->next; } return NULL; }

2.9 单链表在pos之前插入

void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) { assert(pphead);//&plist assert(pos); //assert(*pphead); //一个节点 if (*pphead == NULL) { SLPushFront(pphead, x); } else//多个节点 { SLTNode* prev = *pphead; while (prev->next != pos) { prev = prev->next; } SLTNode* newnode = BuyLTNode(x); prev->next = newnode; newnode->next = pos; } }

2.10 单链表在pos之后插入

void SLInsertAfter(SLTNode* pos, SLTDataType x) { assert(pos); SLTNode* newnode = BuyLTNode(x); newnode->next = pos->next; pos->next = newnode; }

2.11 单链表删除pos的值

void SLErase(SLTNode** pphead, SLTNode* pos) { assert(pphead); assert(pos); if (pos == *pphead) { SLPopFront(pphead); } else { SLTNode* prev = *pphead; while (prev->next!=pos) { prev = prev->next; } prev->next = pos->next; free(pos); } }

2.12 单链表删除pos之后的值

void SLEraseAfter(SLTNode* pos) { assert(pos); SLTNode* next= pos->next; pos->next = next->next; free(next); }

标签:

单链表的概念,结构和优缺点由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“单链表的概念,结构和优缺点