单链表(含代码)
❀叨叨两句:
前面已经介绍过线性表有两种存储方式:顺序与链式。
✌顺序存储方式相关内容在这儿:--->https://mp.youkuaiyun.com/postedit/93474277
需要注意的是两种存储方式的优缺点:
- 顺序表:读取查找时很方便,直接根据索引查询即可,时间复杂度为O(1);但在插入删除等存取操作时需要移动大量元素,时间复杂度为O(n)
- 单链表:与顺序表相反,在存取数据时不需要移动大量元素,只需修改部分节点的指针即可,时间复杂度为O(1);但在查找定位等操作时需要逐个遍历,时间复杂度为O(n)。
言归正传:
1. ✍单链表长这样:

2. ✍因此这样定义:
typedef struct node{
int data;//数据域:存放数据
struct node* Next;//指针域: 下个节点的存放地址
}Node, *Linklist;
3.✍插入节点时的原理图:

4.✍删除操作原理图:

5.✍具体操作+具体解释+具体测试
具体操作有:创建,遍历,判空,定位,插入,删除,获取长度,合并两表
以下代码超长,可能引起不适:
//单链表的基本操作
#include<stdio.h>
#include<stdlib.h>
//结点定义
typedef struct node{
int data;//数据域:存放数据
struct node* Next;//指针域: 下个节点的存放地址
}Node, *Linklist;
//操作声明
Linklist createList();
void traverse(Linklist Head);
bool isEmpty(Linklist Head);
int length(Linklist Head);
bool insert(Linklist Head,int lenth, int pos, int val);
bool del(Linklist Head, int lenth,int pos);
Linklist get(Linklist Head, int value);
Linklist locate(Linklist Head, int k);
void MergeLinklist(Linklist &La,Linklist &Lb,Linklist &Lc);
int main(void)
{
//test
Linklist La=createList();
Linklist Lb=createList();
Linklist Lc=(Linklist)malloc(sizeof(Node));;
Lc->Next=NULL;
int lena=length(La);
int lenb=length(Lb);
int lenc=length(Lc);
printf("\n La的长度是%d,Lb的长度是%d,Lc的长度是%d\n",lena,lenb,lenc);
//遍历测试
printf("\n 当前表La中的数据有 \n");
traverse(La);
printf("\n 当前表Lb中的数据有 \n");
traverse(Lb);
//查找测试
Linklist p=get(La,1);//获取La中data=1的节点
printf("\nLa中data=1的节点数据为%d\n",p->data);
Linklist q=locate(Lb,1); //获取Lb的第1个节点
printf("\nLb的第1个节点存放的数据为%d\n",q->data);
//插入数据测试
insert(La,lena,3,3);
insert(Lb,lenb, 1,4);
lena=length(La);
lenb=length(Lb);
lenc=length(Lc);
printf("\n在第三个位置插入数据3后La的长度是%d,Lb插入新数据后的长度是%d,Lc的长度是%d",lena,lenb,lenc);
printf("\n第一个位置插入数据3后表La中的数据有\n");
traverse(La);
printf("\n在表Lb中第一个位置插入数据4后的数据有\n");
traverse(Lb);
//删除数据测试
del(La,lena, 3);
del(Lb, lenb,1);
printf("\n表La中的数据有\n");
traverse(La);
printf("\n表Lb中的数据有\n");
traverse(Lb);
MergeLinklist(La,Lb,Lc);
printf("\n表Lc中的数据有\n");
traverse(Lc);
return 0;
}
// 1.创建链表
Linklist createList(){
int len,value;
Linklist head=(Linklist)malloc(sizeof(Node));
Linklist rear=head;//尾指针初始化
rear->Next=NULL;//到此已经创建了一个空链表
printf("请输入您所要插入的节点数:");
scanf("%d",&len);
printf("请逐个输入您所要插入的数据:");
for(int i=0;i<len;i++)
{
scanf("%d",&value);
//需提前新建结点接收保存数据,再插入尾部
Linklist nnode=(Linklist)malloc(sizeof(Node));
nnode->data=value;
/*尾结点是rear ,插入一个数据需将tail的next设置为保存数据的新节点nnode,
保证nnode加入链表成为新的尾结点,再将rear更新成尾结点 */
rear->Next=nnode;
rear=nnode;
rear->Next=NULL;
}
return head;//返回头指针
}
//2.遍历链表
void traverse(Linklist head){
Linklist travel=head;//从头开始,但头结点不存储数据
while(travel->Next)//只要后面还有节点,也即travel->next !=NULL
{
travel=travel->Next;//因为头结点不存数据所以输出时先将travel后移;
printf("%d ",travel->data);
}
printf("\n");
}
//3.判断链表是否为空
bool isEmpty(Linklist Head){
if(Head->Next==NULL)
return true;
else{
return false;
}
}
//4.链表长度(不计头结点)
int length(Linklist Head){
int len = 0;
while(Head->Next!=NULL){
Head =Head->Next;
len++;//从头结点后的第一个节点开始计数,头节点不算 哈
}
return len;
}
// 5.插入结点
bool insert(Linklist Head,int lenth, int pos, int value){
//先判断插入位置是否合法
if(pos<1||pos>lenth) return false;
Linklist nnode=(Linklist)malloc(sizeof(Node));
nnode->data=value;
//遍历寻找插入位置de前一个节点 ,注意循环终止条件
Linklist pre=Head;
for(int i=1;i<pos;i++)
{
pre=pre->Next;
}
nnode->Next=pre->Next;//注意插入规则,先后连,再前连,防止断链
pre->Next=nnode;
}
//6.删除结点
bool del(Linklist Head, int lenth,int pos){
if(pos<1 || pos>lenth){
return false;
}else{
Linklist Del = Head;
for(int i=1;i<pos;i++){
Del = Del->Next;//同样也是找到删除位置的前一个节点
}
if(pos==lenth){
//若插入位置在尾部
free(Del->Next);//直接释放最后一个节点即可
Del->Next = NULL;
}else{
Linklist double_Next = Del->Next->Next;
free(Del->Next);
Del->Next = double_Next;
}
//其实两种情况可以合并,不用刻意去分开,直接用else里的代码就行,当插入尾部时double_Next为NULL而已
return true;
}
}
//7.查找节点
//(1)按元素值查找
Linklist get(Linklist Head, int value){
Linklist p = Head->Next;
while(p&&p->data!=value){ //NULL 是 0
p = p->Next;
}
if(!p){
printf("无此节点~\n");
return NULL;
}
return p;
}
//(2)按序号查找
Linklist locate(Linklist Head, int k){
Linklist p = Head;
for(int i=1;i<=k;i++){
p = p->Next;
}
return p;
}
//归并两表1(无去重,结果无序)
void MergeLinklist(Linklist &La,Linklist &Lb,Linklist &Lc)
{
Linklist pa=La->Next;
Linklist pb=Lb->Next;
Linklist pc=Lc;
while(pa&&pb){
if(pa->data >=pb->data){
pc->Next=pb;
pc=pb;
pb=pb->Next;
}else{
pc->Next=pa;
pc=pa;
pa=pa->Next;
}
}
while(pa){
pc->Next=pa;
pc=pa;
pa=pa->Next;
}
while(pb){
pc->Next=pb;
pc=pb;
pb=pb->Next;
}
}
6.✍运行结果:

7.✍正经致谢: