单链表基本操作进阶版
网上太多太多重复的单链表基本操作,无非就是增删改查。本篇在增删改查的基础上进阶了很多其他功能,便于大家深刻理解单链表的含义。
文章开始把我喜欢的这句话送个大家:这个世界上还有什么比自己写的代码运行在一亿人的电脑上更酷的事情吗,如果有那就是让这个数字再扩大十倍!!!
尽请期待更新......
主要函数功能
- 初始化
- 表长
- 判空
- 清空
- 输出
- 按位查找
- 按值查找
- 头插法
- 尾插法
- 按位序插入(在该位序的前一个节点停住)
- 按位序删除(在该位序的前一个节点停住)
- 按值删除
- 递归实现删除x的值
- 从尾到头输出单链表的值(调用时要传入L->next)
- 删除链表中最小的值(假设唯一)
- 单链表就地逆置(空间复杂度O(1)):原理基于头插法
- 使单链表元素递增有序
- 删除规定范围内的数
- 使单链表元素递增输出,输出后释放该结点空间(不可用数组作为辅助空间)
- 将单链表A分解成A、B两个(A:存放奇数位序的数,B:存放偶数位序的数)
-
将单链表C(a1,a2,a3,a4,a5)拆分成两个链表A(a1,a3,a5)和B(a4,a2)
-
将有序递增单链表去重
-
将两个递增的单链表合并为递减的单链表
-
将A、B的公共元素生成单链表C(不破坏A、B)
-
A、B单调递增,将A、B交集存放至A中
-
两个单链表A、B,判断B是不是A的连续子序列
-
查看倒数第K个元素
-
(a1,a2,a3,...,an-2,an-1,an)--->(a1,an,a2,an-1,...)
初始化
bool InitList(LinkList &L)
{
L=(LNode*)malloc(sizeof(LNode));
if(L==NULL) //内存不足,分配失败
return false;
L->next=NULL; //头结点之后还没有结点
return true;
}
表长
bool Length(LinkList L)
{
int j=0;
LNode *p=L;
while(p->next!=NULL)
{
j++;
p=p->next;
}
printf("该单链表长度为:%d\n",j);
return true;
}
判空
bool Empty(LinkList L)
{
if(L->next==NULL)
printf("该表是空表!\n");
else
printf("该表不是空表!\n");
return true;
}
清空
bool ClearList(LinkList &L)
{
LNode *p;
while(L->next!=NULL)
{
p=L->next;
L->next=p->next;
free(p);
}
return true;
}
输出
bool PrintList(LinkList L)
{
if(L->next==NULL)
{
printf("该单链表目前为空表!\n");
return false;
}
while(L->next!=NULL)
{
L=L->next;
printf("%d ",L->data);
}
printf("\n");
}
按位查找
bool GetElem(LinkList L,int i)
{
if(i<1)
return false;
int j=1;
LNode *p=L->next;
while(p!=NULL&&j<i)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
printf("位序%d的数据是%d\n",i,p->data);
}
按值查找
bool LocalEmem(LinkList L,int e)
{
int j=1;
LNode *p=L->next;
while(p!=NULL&&p->data!=e)
{
j++;
p=p->next;
}
if(p==NULL)
{
printf("未在该单链表中找到%d数据\n",e);
return false;
}
printf("%d的在单链表中位序是:%d\n",e,j);
return true;
}
头插法
LinkList List_HeadInsert(LinkList &L)
{
int x;
while(scanf("%d",&x)!=EOF)
{
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
}
return L;
}
尾插法
LinkList List_TailInsert(LinkList &L)
{
int x;
LNode *r=L;
while(scanf("%d",&x)!=EOF)
{
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=r->next;
r->next=s;
r=r->next; //r=s;
}
r->next=NULL;
return L;
}
按位序插入(在该位序的前一个节点停住)
bool ListInsert(LinkList L,int i,int e)
{
if(i<1)
return false;
int j=0;
LNode *p=L;
while(p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if(p==NULL) //i不合法
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
按位序删除(在该位序的前一个节点停住)
bool ListDeleteLocal(LinkList &L,int i)
{
if(i<1)
return false;
int j=0;
LNode *p=L;
while(p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if(p->next==NULL) //i不合法***
return false;
LNode *q=p->next;
p->next=q->next;
free(q);
return true;
}
按值删除
bool ListDeleteElem(LinkList &L,int e)
{
LNode *p=L->next;
LNode *q=L;
while(p!=NULL)
{
if(p->data==e)
{
q->next=p->next;
free(p);
p=q->next;
}
else
{
p=p->next;
q=q->next;
}
}
return true;
}
递归实现删除x的值
void Del_X(LinkList &L,int x)
{
if(L->next==NULL)
return;
if(L->next->data==x)
{
LNode *p=L->next;
L->next=p->next;
free(p);
Del_X(L,x);
}
else
Del_X(L->next,x);
}
从尾到头输出单链表的值(调用时要传入L->next)
void R_Print(LinkList L)
{
if(L==NULL)
return;
R_Print(L->next);
printf("%d ",L->data);
}
删除链表中最小的值(假设唯一)
void Delete_Min(LinkList &L)
{
LNode *pre=L,*p=L->next;
LNode *minp=pre,*min=p;
while(p!=NULL) //找到最小值的结点前驱结点
{
if(min->data>p->data)
{
min=p;
minp=pre;
}
p=p->next;
pre=pre->next;
}
minp->next=min->next; //删除最小值的结点
free(min);
}
单链表就地逆置(空间复杂度O(1)):原理基于头插法
void Reverse_O1(LinkList &L)
{
LNode *p=L->next,*r;
L->next=NULL;
while(p!=NULL)
{
r=p->next; //暂存p的下一个结点
p->next=L->next;
L->next=p;
p=r;
}
}
使单链表元素递增有序
void Sort(LinkList &L)
{
LNode *p=L->next;
LNode *r=p->next;
p->next=NULL; //构建只含有头结点的单链表
p=r;
while(p!=NULL)
{
r=p->next;
LNode *pre=L;
while(pre->next!=NULL&&p->data>pre->next->data)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=r;
}
}
删除规定范围内的数
bool RangeDelete(LinkList &L,int min,int max)
{
if(max<min)
return false;
LNode *p=L->next;
LNode *pre=L;
while(p!=NULL)
{
if(p->data>=min&&p->data<=max)
{
pre->next=p->next;
free(p); //先释放
p=pre->next;
}
else
{
p=p->next;
pre=pre->next;
}
}
return true;
}
使单链表元素递增输出,输出后释放该结点空间(不可用数组作为辅助空间)
void Delete_Min_Desotry(LinkList &L)
{
while(L->next!=NULL)
{
LNode *p=L->next;
LNode *minp=L;
while(p->next!=NULL)
{
if(minp->next->data>p->next->data) //发现比该记录的小,让minp移动到最新的小的前边
minp=p;
p=p->next;
}
printf("%d ",minp->next->data);
LNode *u=minp->next;
minp->next=u->next;
free(u);
}
printf("\n");
free(L);
}
将单链表A分解成A、B两个(A:存放奇数,B:存放偶数)
void DisCreat(LinkList &A,LinkList &B)
{
int i=1;
LNode *p=A->next;
LNode *prea=A;
LNode *preb=B;
while(p!=NULL)
{
if((i++)%2==1)
{
prea->next=p;
prea=p;
}
else
{
preb->next=p;
preb=p;
}
p=p->next;
}
prea->next=NULL;
preb->next=NULL;
}
将单链表C(a1,a2,a3,a4,a5)拆分成两个链表A(a1,a3,a5)和B(a4,a2)
void DisCreat2(LinkList &A,LinkList &B)
{
int i=1;
LNode *p=A->next;
LNode *prea=A;
LNode *preb=B; //头插
preb->next=NULL;
while(p!=NULL)
{
if((i++)%2==1)
{
prea->next=p;
prea=p;
p=p->next;
}
else
{
LNode *q=p;
p=p->next;
q->next=B->next;
B->next=q;
}
}
prea->next=NULL;
}
将有序递增单链表去重
void Del_Same(LinkList &L)
{
LNode *p=L->next;
if(p==NULL) //只有一个结点
return;
while(p->next!=NULL)
{
if(p->data==p->next->data)
{
LNode *q=p->next;
p->next=q->next;
free(q);
}
else
p=p->next;
}
}
将两个递增的单链表合并为递减的单链表
void MergeList(LinkList &A,LinkList &B)
{
LNode *pa=A->next;
LNode *pb=B->next;
LNode *L=A; //头插
L->next=NULL;
while(pa!=NULL&&pb!=NULL)
{
if(pa->data<pb->data)
{
LNode *q=pa; //LNode *r=pa->next;
pa=pa->next; //pa->next=L->next;
q->next=L->next; //L->next=pa;
L->next=q; //pa=r;
}
else
{
LNode *q=pb;
pb=pb->next;
q->next=L->next;
L->next=q;
}
}
while(pa!=NULL)
{
LNode *q=pa;
pa=pa->next;
q->next=L->next;
L->next=q;
}
while(pb!=NULL)
{
LNode *q=pb;
pb=pb->next;
q->next=L->next;
L->next=q;
}
}
将A、B的公共元素生成单链表C(不破坏A、B)
void Get_Common(LinkList A,LinkList B,LinkList &C)
{
LNode *pa=A->next;
LNode *pb=B->next;
LNode *prec=C,*r=C; //尾插,原顺序保持不变
while(pa!=NULL&&pb!=NULL)
{
if(pa->data<pb->data)
pa=pa->next;
else if(pa->data>pb->data)
pb=pb->next;
if(pa->data==pb->data)
{
LNode *s=(LNode*)malloc(sizeof(LNode)); //复制该结点
s->data=pa->data;
r->next=s; //尾插
r=s;
r->next=NULL;
pa=pa->next;
pb=pb->next;
}
}
}
A、B单调递增,将A、B交集存放至A中
void Get_Intersection(LinkList &A,LinkList B)
{
LNode *pa=A->next;
LNode *pb=B->next;
LNode *r=A; //尾插
A->next=NULL;
while(pa!=NULL&&pb!=NULL)
{
if(pa->data<pb->data)
pa=pa->next;
else if(pa->data>pb->data)
pb=pb->next;
else
{
LNode *next_pa=pa->next;
pa->next=r->next;
r->next=pa;
r=pa;
pa=next_pa;
pb=pb->next;
}
}
}
两个单链表A、B,判断B是不是A的连续子序列
bool KMP(LinkList A,LinkList B)
{
LNode *pa=A->next;
LNode *pb=B->next;
while(pa!=NULL) //主串不为空
{
if(pa->data!=pb->data) //不等,主串后移一位
{
pa=pa->next;
}
else
{
LNode *copy_pa=pa; //pa的复制指针,用来判断该结点开头的序列是否和B相同
while(copy_pa!=NULL&&pb!=NULL)
{
if(copy_pa->data!=pb->data)
break;
copy_pa=copy_pa->next;
pb=pb->next;
}
if(pb==NULL) //pb走到了B的走后边
return true;
else
{
pa=pa->next; //主串走下一个,副串回到最开始
pb=B->next;
}
}
}
return false;
}
查看倒数第K个元素
bool Search_K(LinkList L,int k)
{
LNode *p=L->next;
LNode *q=L->next;
int count=1;
while(count<k&&p!=NULL)
{
count++;
p=p->next;
}
if(count<k||k<1)
return false;
while(p->next!=NULL)
{
p=p->next;
q=q->next;
}
printf("%d",q->data);
return true;
}
(a1,a2,a3,...,an-2,an-1,an)--->(a1,an,a2,an-1,...)
void Change(LinkList &L)
{
LNode *p1=L;
LNode *p2=L;
while(p2->next!=NULL) //找到中间结点p1
{
p1=p1->next;
p2=p2->next;
if(p2->next!=NULL)
p2=p2->next;
else
break;
}
p2=p1->next; //头插后边部分原地逆置
p1->next=NULL;
while(p2!=NULL)
{
LNode *r=p2->next;
p2->next=p1->next;
p1->next=p2;
p2=r;
}
p2=p1->next; //分别依次根据p1、p2、p1、p2...排序
LNode *p1_end=p1->next;
p1=L->next;
L->next=NULL; //尾插法
LNode *r=L;
while(1)
{
if(p1==p1_end&&p2==NULL)
break;
LNode *r1=p1->next;
p1->next=r->next;
r->next=p1;
r=r->next;
p1=r1;
if(p1==p1_end&&p2==NULL)
break;
LNode *r2=p2->next;
p2->next=r->next;
r->next=p2;
r=r->next;
p2=r2;
}
}
************************************************************************************************************
您的建议是博主更新最大的动力!!
如发现错误请在评论区评论,博主会仔细查看并修改的!!
希望对您有所帮助!!!