目录
引言
一:链表的定义
二:单链表的定义
三:单链表的增删查改
1.单链表增删查改及遍历的声明
注:在测试中创建指向头结点的指针plist
2.二级指针应用的说明
3.单链表的遍历
4.创建节点
5.单链表的插入
(1)头插
(2) 尾插
(3)任意位置之前插入
(4)任意位置之后插入
6.单链表的删除
(1)头删
(2) 尾删
(3) 任意位置删除
7.单链表的查找
8.单链表的修改
四:关于单链表的介绍就到此为止了,青山不改,绿水长流,后会有期。
接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧
引言
链表是一种常见的数据结构,它可以用来存储数据,并可以快速的进行增删查改的目的。相对于数组来说链表更加灵活和高效,数组的优势在于数组下标的随机访问,链表则可以更好的解决数组容量的大小,频繁扩容等一系列问题。
接下来本文将介绍关于链表的定义以及单链表的增删查改,知识云游号即将发车
辞忧提醒你请系好安全带,准备发车
一:链表的定义
1.链表是由一系列的节点构成,每个节点包含一个数据内容的数据域和一个指向下一个节点的指针的指针域。
2.每个节点是由malloc申请来的,所以每个节点是在内存空间中的堆区中,并且是在堆中随即申请的,所以各结点的地址是不连续的,是随机的。并且与在栈中申请的局部变量不同,局部变量出作用域销毁,而节点是在堆中,不销毁。
3.每个链表都包含一个头节点和一个指向头结点的指针变量,用来对链表进行各种操作。每个链表的尾节点中指针域为NULL。
二:单链表的定义
三:单链表的增删查改
1.单链表增删查改及遍历的声明
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SListDatatype;typedef struct SListNode
{SListDatatype data;struct SListNode* next;
}SLTNode;//打印单链表数据
void SLTPrint(SLTNode*phead);//单链表之创建节点
SLTNode* CreatNode(SListDatatype x);//单链表之头插
void SLTPushFront(SLTNode** pphead,SListDatatype x);//单链表之尾插
void SLTPushBack(SLTNode** pphead, SListDatatype x);//单链表之头删
void SLTPopFront(SLTNode**pphead);//单链表之尾删
void SLTPopBack(SLTNode **pphead);//单链表之查找
SLTNode* SLTFindData(SLTNode** pphead, SListDatatype data);//单链表之修改
void SLTModifyData(SLTNode** pphead, SListDatatype place,SListDatatype data);//单链表之任意位置之前插入
void SLTPushArbit(SLTNode**pphead,SListDatatype place,SListDatatype data);//单链表之任意位置删除
void SLTPopArbit(SLTNode** pphead, SListDatatype place);//单链表之任意位置之后插入
void SLTPushBackArbit(SLTNode** pphead, SListDatatype place, SListDatatype data);
注:在测试中创建指向头结点的指针plist
2.二级指针应用的说明
二级指针顾名思义就是指向指针的指针,在最早接触指针的时候,有一个最简单的例子,就是用函数来实现两数交换,这个问题最初我们写的代码就如下
发现根本没有解决问题,主要原因是改变形参不改变实参,因此便想到运用指针的方法:
这次发现 便可以,因此要改变int类型的值必须传int*,改变int*的值必须传int**,对于单链表中的结构体也一样,改变头节点的指针,就得使用头节点指针的指针。
3.单链表的遍历
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->",cur->data);cur = cur->next;}printf("NULL\n");
}
4.创建节点
SLTNode* CreatNode(SListDatatype x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc newnode");return ;}newnode->data = x;newnode->next = NULL;return newnode;
}
注:x为数据域的内容
5.单链表的插入
(1)头插
void SLTPushFront(SLTNode** pphead,SListDatatype x)
{assert(pphead);SLTNode* newnode = CreatNode(x);newnode->next = *pphead;*pphead = newnode;
}
(2) 尾插
void SLTPushBack(SLTNode** pphead, SListDatatype x)
{assert(pphead);SLTNode* newnode = CreatNode(x);//1.空链表if (*pphead == NULL){*pphead = newnode;}else //2.不是空链表{//找尾SLTNode* cur = *pphead;while (cur->next != NULL){cur = cur->next;}cur->next = newnode;}
}
(3)任意位置之前插入
//查找代码
SLTNode* SLTFindData(SLTNode** pphead, SListDatatype x)
{assert(pphead);assert(*pphead);//空链表不需查找SLTNode* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
void SLTPushFrontArbit(SLTNode** pphead, SListDatatype place,SListDatatype data)
{assert(pphead);assert(*pphead);//空链表不能任意位置插入SLTNode* PushPlace = SLTFindData(pphead, place);if (PushPlace != NULL){if (PushPlace == *pphead)//1.只有一个节点{SLTPushFront(pphead, data);}else//2.一个以上节点{SLTNode* newnode = CreatNode(data);SLTNode* cur = *pphead;while (cur->next != PushPlace){cur = cur->next;}cur->next = newnode;newnode->next = PushPlace;}}else{printf("无此位置");return;}
}
(4)任意位置之后插入
SLTNode* SLTFindData(SLTNode** pphead, SListDatatype x)
{assert(pphead);assert(*pphead);//空链表不需查找SLTNode* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
void SLTPushBackArbit(SLTNode** pphead, SListDatatype place, SListDatatype data)
{assert(pphead);assert(*pphead);//空链表不需查找插入SLTNode* PushPlace = SLTFindData(pphead, place);if (PushPlace){SLTNode* newnode = CreatNode(data);if (*pphead == PushPlace)//头节点之后插入{(*pphead)->next = newnode;}else if(PushPlace->next==NULL)//尾节点之后插入{SLTNode* cur = *pphead;while (cur != PushPlace){cur = cur->next;}cur->next = newnode;}else{SLTNode* cur = *pphead;while (cur != PushPlace){cur = cur->next;}SLTNode* curr = cur->next;newnode->next = curr;cur->next = newnode;}}else{printf("找不到");return;}
}
6.单链表的删除
(1)头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);//空链表不能删除//1.只有一个节点if ((*pphead)->next == NULL){*pphead = NULL;free(*pphead);}else //2.一个以上节点{SLTNode* del = *pphead;*pphead = del->next;del->next = NULL;free(del);}
}
(2) 尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead);assert(*pphead);//空链表不能删除//1.只有一个节点if ((*pphead)->next == NULL){*pphead = NULL;free(*pphead);}else{SLTNode* cur = *pphead;while (cur->next->next != NULL){cur = cur->next;}cur->next = NULL;free(cur->next);}
}
(3) 任意位置删除
//查找
SLTNode* SLTFindData(SLTNode** pphead, SListDatatype x)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
void SLTPopArbit(SLTNode** pphead, SListDatatype place)
{assert(pphead);assert(*pphead);//空链表不能查找删除SLTNode* PopPlace = SLTFindData(pphead, place);if (PopPlace != NULL){if (*pphead == PopPlace)//只有一个节点{SLTPopFront(pphead);}else{SLTNode* cur = *pphead;while (cur->next != PopPlace){cur = cur->next;}SLTNode* del = PopPlace;cur->next = del->next;free(del);}}else{printf("无此位置");return;}
}
7.单链表的查找
SLTNode* SLTFindData(SLTNode** pphead, SListDatatype x)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
8.单链表的修改
//指定位置修改
void SLTModifyData(SLTNode** pphead, SListDatatype place,SListDatatype data)
{assert(pphead);assert(*pphead);//空链表不能修改SLTNode* ret = SLTFindData(pphead, place);ret->data = data;
}