一、运行效果
完整程序在末尾。
1、链表储存结构
typedef struct LNode{ //定义单链表结点类型
elemtype data; //数据域
struct LNode *next; //指针域
}Lnode, *Linklist;
typedef int status;
链表由指针域来连接各结点,确保链表线性连续。
2、初始化—头插法
status Initlist(Linklist &l){
Linklist p,q;
l=(Linklist)malloc(sizeof(Lnode));
p=(Linklist)malloc(sizeof(Lnode));
p=l;
printf("请输入链表长度:");
int len;
scanf("%d",&len);
printf("请输入链表元素:");
for(int j=1;j<=len;j++){
q=(Linklist)malloc(sizeof(Lnode));
scanf("%d",&q->data);
p->next=q;
p=q;
}
p->next=NULL;
return ok;
}
首先,定义两指针结点p、q,p指向L(头结点),生成q,且p->next=q,利用scnaf输入q->data,然后将p指向q,如此在for循环中,不断生成新结点q,p又随之指向下一结点,最后将p->next=NULL即可。
3、插入
status Insertlist(Linklist &l,int i,elemtype e){
Linklist p,s;
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
s=(Linklist)malloc(sizeof(Lnode));
p=l;
while(p&&j<i-1){
p=p->next;++j;
}
if(!p||j>i-1){return error;}
s->next=p->next;
p->next=s;
s->data=e;
printf("插入成功\n");
js=Printlist(l);
return ok;
}
首先,定义结点指针p、s,通过for循环,将p指向所插入的前一个结点,且s为插入节点,令s->next=p->next;再将p->next=s;如此便成功将s节点插入了。
4、删除
status Deletelist(Linklist &l,int i){
Linklist p,q;
printf("目前删除第%d位节点",i);
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
q=(Linklist)malloc(sizeof(Lnode));
p=l;
while(p&&j<i-1){
p=p->next;++j;
}
q=p->next;
p->next=q->next;
free(q);
printf("删除成功,如下:");
js=Printlist(l);
return ok;
}
首先,生成结点p、q,通过for循环将p指向所删除结点的前一个结点,将q作为中转结点,且q为p的下一结点,q=p->next;再p->next=q->next,再释放q,Free(q);即可。
5、按值查找
status Getlist(Linklist &l,int &i){
Linklist p,q;
elemtype e;
int j=0;
i=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
p=l;
printf("请输入查找的元素:");
fflush(stdin);
scanf("%d",&e);
do{
++i;++j;
p=p->next;
}
while(p&&p->data!=e);
if(p->data==e){
printf("查找成功");
}
else{printf("查找失败");}
printf("该元素位置为:%d",i);
return ok;
}
生成结点p,将p指向头结点L,通过在do-while函数中比对所输入的值与链表结点data,取相等时候的第一个结点的位置。
6、打印
status Printlist(Linklist L){
Linklist p;
p=(Linklist)malloc(sizeof(Lnode));
p=L->next;
if(!p){return error;}
while(p){
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return ok;
}
生成结点p,将p指向头结点L,在while循环中不断输出p->data,直至打印到p->next=NULL为止。
7、单链表逆置
status Reverselist(Linklist &l){
Linklist p,q,s;
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
q=(Linklist)malloc(sizeof(Lnode));
s=(Linklist)malloc(sizeof(Lnode));
p=l->next;
q=p->next;
p->next=NULL;
s=q->next;
q->next=p;p=q;q=s;
while(s){
s=q->next;
q->next=p;p=q;q=s;
}
l->next=p;
printf("逆置后的链表如下:");
js=Printlist(l);
return ok;
}
首先,生成结点指针p、q、s;
第一阶段,p指向L->next,q指向p->next,将p->next=NULL赋空值,令s=q->next,再将q->next赋给p,即将q指向p,再移位,p=q;q=s;
第二阶段,循环;利用s=q->next;可以放心将q指向p,再移位即可,
最后,将头结点指向p。
8、清除
void Clearlist(Linklist &L) {
Linklist p;
while (L->next) {
p = L->next;
L->next = p->next;
free(p);
}
printf("清空成功");
}
生成结点指针p,在循环中,将p指向L->next,并移动头指针,指向p->next,接着释放p,如结点1、 2、3,p指向1,L最后指向2,然后删除1即可。
9、销毁
void Destroylist(Linklist &L) {
Linklist p;
p=L;
while (p)
{
L = L->next;
// free(p);
delete(p);
p = L;
}
printf("销毁成功");
}
生成结点指针p,在循环中,移动头指针,指向下一结点,令p=L,不断删除上一结点,并将原头结点L不断指向下一结点,最后L将指向NULL。
10、归并
void Mergelist(Linklist &la,Linklist &lb,Linklist &lc){
Linklist pa,pb,pc;
pa=(Linklist)malloc(sizeof(Lnode));
pb=(Linklist)malloc(sizeof(Lnode));
pc=(Linklist)malloc(sizeof(Lnode));
pa=la->next;pb=lb->next;
lc=pc=la;
while(pa&&pb){
if(pa->data<=pb->data){
pc->next=pa;pc=pa;pa=pa->next;
}
else{pc->next=pb;pc=pb;pb=pb->next;}
}
pc->next=pa?pa:pb;
free(lb);
printf("归并LC链表如下:");
js=Printlist(lc);
}
生成两结点pa、pb,由于La,Lb为单调递增有序链表,且将pa指向La->next,
Pb指向Lb->next,通过比较pa->data和pb->data,将较小的插入Lc中,直至La或Lb其中一个全部插入完成,则剩下的链表全部插入Lc即可
11、去重
void Distinctlist(Linklist &l)
{
Lnode *p,*mark,*q;
for(mark=l->next;mark!=NULL;mark=mark->next)
{
q=mark;
p=mark->next;
while(p)
{
if(mark->data==p->data)
{
q->next=p->next;
free(p);
p=q->next;
}else
{
q=p;
p=p->next;
}
}
}
printf("去重后如下:");
js=Printlist(l);
}
原理为,将链表第i=1个结点(比对结点)的data与其余结点的data比对是否相等,然后i++;随之将下一结点比对其后面的结点的data,直至结点为NULL。
生成结点p、mark、q;在for循环中,mark为比对结点,并令q=mark,p为mark所指向的结点,通过比对p结点的data(p->data),如果相等,采用删除结点函数的方法使链表连续,并将p指向q->next,否则,p指向下一结点p=p->next。
12、分解
void Devide(Linklist &La,Linklist &Lb,Linklist &Lc)
{
int count=0;
Lb=(Lnode *)malloc(sizeof(Lnode));
Lc=(Lnode *)malloc(sizeof(Lnode));
Lnode *p,*q,*r;
p=La;q=Lb;r=Lc;
while(p!=NULL&&p->next!=NULL){
count++;
p=p->next;
if(count%2!=0){q->next=p;q=q->next;}
else{r->next=p;r=r->next;}
}
r->next=NULL;
q->next=NULL;
printf("分解两链表如下:\n");
printf("奇数链表 Lb: ");
js=Printlist(Lb);
printf("偶数链表 Lc: ");
js=Printlist(Lc);
}
生成结点p、q、r,并设立计数器count,且将p指向La,q指向Lb,r指向Lc,在while循环中,第一次循环,count++,当前为结点1,如果count%2!=0,即当前结点为奇数结点,将该结点赋给q->next,即将q(Lb)指向该节点,并将q指向自己的下一结点,如果count%2==0,即当前结点为偶数结点,将该结点赋给r->next,即将r(Lc)指向该节点,并将r指向自己的下一结点。最后将r和q指向NULL,即La分配完毕后。
此外,还有一种方法:
void Devide(Linklist &La,Linklist&Lb,Linklist&Lc)
{
Linklist p,q,r; //p用来指向Lb
r=La->next;
Lb=(Linklist)malloc(sizeof(LinkNode));
Lc=(Linklist)malloc(sizeof(LinkNode));
p=Lb;
q=Lc; //q用来指向Lc
while(r!=NULL&&r->next!=NULL)
{
p->next=r;
p=p->next;
q->next=r->next;
q=q->next;
r=r->next->next;
}
p->next=NULL;
q->next=NULL;
}
生成两结点指针,p、q;p用来指向Lb、q用来指向Lc;在while循环中,第一次循环时,p的next指向r,并将p赋为p->next,即将p下移一位,q也同理,并将r指向r的next的next,即在下一次循环中不影响前一次的分配,直至r指向NULL。最后将p、q指向NULL;
此思路源自这位:
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#define ok 1
#define error 0
typedef int elemtype;
typedef int status;
typedef struct LNode{ //定义单链表结点类型
elemtype data; //数据域,可以是别的各种数据类型,本文统一用int类型
struct LNode *next; //指针域
}Lnode, *Linklist;
typedef int status;
int js;
status Printlist(Linklist L);
// 初始化,头插法
status Initlist(Linklist &l){
Linklist p,q;
l=(Linklist)malloc(sizeof(Lnode));
p=(Linklist)malloc(sizeof(Lnode));
p=l;
printf("请输入链表长度:");
int len;
scanf("%d",&len);
printf("请输入链表元素:");
for(int j=1;j<=len;j++){
q=(Linklist)malloc(sizeof(Lnode));
scanf("%d",&q->data);
p->next=q;
p=q;
}
p->next=NULL;
return ok;
}
// 插入
status Insertlist(Linklist &l,int i,elemtype e){
Linklist p,s;
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
s=(Linklist)malloc(sizeof(Lnode));
p=l;
while(p&&j<i-1){
p=p->next;++j;
}
if(!p||j>i-1){return error;}
s->next=p->next;
p->next=s;
s->data=e;
printf("插入成功\n");
js=Printlist(l);
return ok;
}
// 删除
status Deletelist(Linklist &l,int i){
Linklist p,q;
printf("目前删除第%d位节点",i);
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
q=(Linklist)malloc(sizeof(Lnode));
p=l;
while(p&&j<i-1){
p=p->next;++j;
}
q=p->next;
p->next=q->next;
free(q);
printf("删除成功,如下:");
js=Printlist(l);
return ok;
}
// 查找链表某元素并返回位置
status Getlist(Linklist &l,int &i){
Linklist p,q;
elemtype e;
int j=0;
i=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
p=l;
printf("请输入查找的元素:");
fflush(stdin);
scanf("%d",&e);
do{
++i;++j;
p=p->next;
}
while(p&&p->data!=e);
if(p->data==e){
printf("查找成功");
}
else{printf("查找失败");}
printf("该元素位置为:%d",i);
return ok;
}
// 打印
status Printlist(Linklist L){
Linklist p;
p=(Linklist)malloc(sizeof(Lnode));
p=L->next;
if(!p){return error;}
while(p){
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return ok;
}
// // 单链表逆置
status Reverselist(Linklist &l){
Linklist p,q,s;
int j=0;
p=(Linklist)malloc(sizeof(Lnode));
if(!p){return error;}
q=(Linklist)malloc(sizeof(Lnode));
s=(Linklist)malloc(sizeof(Lnode));
p=l->next;
q=p->next;
p->next=NULL;
s=q->next;
q->next=p;p=q;q=s;
while(s){
s=q->next;
q->next=p;p=q;q=s;
}
l->next=p;
printf("逆置后的链表如下:");
js=Printlist(l);
return ok;
}
//清除
void Clearlist(Linklist &L) {
Linklist p;
while (L->next) {
p = L->next;
L->next = p->next;
free(p);
}
printf("清空成功");
}
//销毁
void Destroylist(Linklist &L) {
Linklist p;
p=L;
while (p)
{
L = L->next;
// free(p);
delete(p);
p = L;
}
printf("销毁成功");
}
// 归并
void Mergelist(Linklist &la,Linklist &lb,Linklist &lc){
Linklist pa,pb,pc;
pa=(Linklist)malloc(sizeof(Lnode));
pb=(Linklist)malloc(sizeof(Lnode));
pc=(Linklist)malloc(sizeof(Lnode));
pa=la->next;pb=lb->next;
lc=pc=la;
while(pa&&pb){
if(pa->data<=pb->data){
pc->next=pa;pc=pa;pa=pa->next;
}
else{pc->next=pb;pc=pb;pb=pb->next;}
}
pc->next=pa?pa:pb;
free(lb);
printf("归并LC链表如下:");
js=Printlist(lc);
}
// 去重
void Distinctlist(Linklist &l)
{
Lnode *p,*mark,*q;
for(mark=l->next;mark!=NULL;mark=mark->next)
{
q=mark;
p=mark->next;
while(p)
{
if(mark->data==p->data)
{
q->next=p->next;
free(p);
p=q->next;
}else
{
q=p;
p=p->next;
}
}
}
printf("去重后如下:");
js=Printlist(l);
}
分解
void Devide(Linklist &La,Linklist &Lb,Linklist &Lc)
{
int count=0;
Lb=(Lnode *)malloc(sizeof(Lnode));
Lc=(Lnode *)malloc(sizeof(Lnode));
Lnode *p,*q,*r;
p=La;q=Lb;r=Lc;
while(p!=NULL&&p->next!=NULL){
count++;
p=p->next;
if(count%2!=0){q->next=p;q=q->next;}
else{r->next=p;r=r->next;}
}
r->next=NULL;
q->next=NULL;
printf("分解两链表如下:\n");
printf("Lb: ");
js=Printlist(Lb);
printf("Lc: ");
js=Printlist(Lc);
}
// 分解2
//void Devide(Linklist &La,Linklist&Lb,Linklist&Lc)
//{
// Linklist p,q,r; //p用来指向Lb
// r=La->next;
// Lb=(Linklist)malloc(sizeof(LinkNode));
// Lc=(Linklist)malloc(sizeof(LinkNode));
// p=Lb;
// q=Lc; //q用来指向Lc
// while(r!=NULL&&r->next!=NULL)
// {
// p->next=r;
// p=p->next;
// q->next=r->next;
// q=q->next;
// r=r->next->next;
// }
// p->next=NULL;
// q->next=NULL;
//}
int main()
{
Linklist L,la,lb,lc,ld,le;
js=Initlist(L);
js=Insertlist(L,2,6);
js=Printlist(L);
js=Deletelist(L,3);
js=Getlist(L,js);
printf("\n");
js=Reverselist(L);
Distinctlist(L);
Clearlist(L);
printf("\n");
Destroylist(L);
printf("\n");
printf("初始化链表La、Lb\n");
js=Initlist(la);
js=Initlist(lb);
Mergelist(la,lb,lc);
printf("分解链表Lc");
Devide(lc,ld,le);
return 0;
}