题目
设指针la和lb分别指向两个无头结点单链表中的首结点,试设计从表la中删除自第i个元素起共len个元素,并将它们插入到表lb的第j个元素之后的算法。
根据题目可知我们可以使用查询函数找到第一个删除的地方(保存它的前驱结点以方便将这一段链表在la中删除掉)然后依据len的长度找到最后一个删除的位置,然后按照删除操作的代码正常对其进行删除即可。插入时也可以使用查询函数对要插在第几个之后进行查找,找到插入结点的前一个结点然后将被删除的结点一个个插入到lb表中即可。
我首先以自己的思考写了一个这样的代码:
运行起来是可以使用的,仅供大家参考使用:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct stu
{
int n;
struct stu *next;
}de;
int Len=0; //判断删除操作是否可以正常运行
de *create1() //与正常的创建链表内容一样 创建La链表
{
de *head,*s,*r;
head=(de *)malloc(sizeof(de));
cout<<"请输入内容:"<<endl;
r=head;
s=(de *)malloc(sizeof(de));
cin>>s->n;
Len++;
while(s->n!=0)
{
r->next=s;
s->next=NULL;
r=s;
s=(de *)malloc(sizeof(de));
cin>>s->n;
Len++;
}
free(s);
return head;
}
de *create2() //创建Lb的链表
{
de *head,*s,*r;
head=(de *)malloc(sizeof(de));
cout<<"请输入内容:"<<endl;
r=head;
s=(de *)malloc(sizeof(de));
cin>>s->n;
while(s->n!=0)
{
r->next=s;
s->next=NULL;
r=s;
s=(de *)malloc(sizeof(de));
cin>>s->n;
}
free(s);
return head;
}
void Delete(de **La,de **Lb,int n,int m,int j) //**指的是二级指针,为链表的地址,可以直接更改链表的值
{
if(Len<n+m)
cout<<"输入的n和m出现问题!"<<endl;
else
{
de *p,*q; //q为前驱结点,p为当前节点
de *h,*r,*s,*b;
h->next=NULL;
s=h;
p=(*La)->next;
while(n-1>0) //找到要删除的第一个元素的结点和它的前驱结点方便后续删除操作
{
q=p;
p=p->next;
n--;
}
r=p;
int x=m; //保存m的值不变化
while(m-1>0)
{
p=p->next; //找到要删除的最后一个结点
m--;
}
q->next=p->next; //将一段元素从链表La中删除
m=x; //将保存的m值再次赋给m可以再次循环使用
b=(*Lb);
while(j--)
b=b->next;
while(m--) //将删除的链表一个一个的插入Lb链表中
{
s=r->next;
r->next=b->next;
b->next=r;
r=s;
}
cout<<"修改后的链表:"<<endl;
cout<<"La:"<<endl;
print(La);
cout<<"Lb"<<endl;
print(Lb);
}
}
void print(de *h)
{
de *t;
t=h->next;
while(t)
{
cout<<t->n<<" ";
t=t->next;
}
cout<<endl;
}
int main()
{
de *La,*Lb,*Lc;
int m,n,j;
La=create1();
cout<<"La:"<<endl;
print(La);
Lb=create2();
cout<<"Lb:"<<endl;
print(Lb);
cout<<"请输入从第几个元素删除->";
cin>>n;
cout<<"请输入要删除多少个数据->";
cin>>m;
cout<<"请要b链表中呢个位置插入->";
cin>>j;
Delete(&La,&Lb,n,m,j);
return 0;
}
对此代码运行的结构如下图所示:
但在此代码中查询一直是在删除的函数里进行,这个函数的内容有些冗长了,我们可以把查询的函数单独放出来形成一个函数对其进行调用返回最后一个结点的值即可。
更改后的代码如下所示;
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct stu
{
int n;
int Len;
struct stu *next;
}de;
de *search(de *p1,int i);
void Delete(de **La,de **Lb,int n,int m,int j);
void print(de *phead);
int Len=0; //判断删除是否可以正常运行
de *create1() //与正常的创建链表内容一样
{
de *head,*s,*r;
head=(de *)malloc(sizeof(de));
cout<<"请输入内容:"<<endl;
r=head;
s=(de *)malloc(sizeof(de));
cin>>s->n;
Len++;
while(s->n!=0)
{
r->next=s;
s->next=NULL;
r=s;
s=(de *)malloc(sizeof(de));
cin>>s->n;
Len++;
}
free(s);
return head;
}
de *create2() //与正常的创建链表内容一样
{
de *head,*s,*r;
head=(de *)malloc(sizeof(de));
cout<<"请输入内容:"<<endl;
r=head;
s=(de *)malloc(sizeof(de));
cin>>s->n;
while(s->n!=0)
{
r->next=s;
s->next=NULL;
r=s;
s=(de *)malloc(sizeof(de));
cin>>s->n;
}
free(s);
return head;
}
void Delete(de **La,de **Lb,int n,int m,int j) //**指的是二级指针,为链表的地址,可以直接更改链表的值
{
if(Len<n+m)
cout<<"输入的n和m出现问题!"<<endl;
else
{
de *p,*q; //q为前驱结点,p为当前节点
de *h,*r,*s,*b;
h->next=NULL;
s=h;
p=(*La);
while(n--) //找到要删除的第一个元素的结点和它的前驱结点方便后续删除操作
{
q=p;
p=p->next;
}
r=p; //保存着删除的第一个节点位置,插入时有用
int x=m; //保存m的值不变化
p=search(p,m-1);
q->next=p->next; //将一段元素从链表La中删除
m=x;
b=search((*Lb),j);
while(m--) //将删除的链表一个一个的插入Lb链表中
{
s=r->next;
r->next=b->next;
b->next=r;
r=s;
}
cout<<"修改后的链表:"<<endl;
cout<<"La:"<<endl;
print((*La));
cout<<"Lb"<<endl;
print((*Lb));
}
}
de *search(de *p1,int i)
{
de *t;
t=p1;
while(i--)
{
t=t->next;
}
return t;
}
void print(de *h)
{
de *t;
t=h->next;
while(t)
{
cout<<t->n<<" ";
t=t->next;
}
cout<<endl;
}
int main()
{
de *La,*Lb,*Lc;
int m,n,j;
La=create1();
cout<<"La:"<<endl;
print(La);
Lb=create2();
cout<<"Lb:"<<endl;
print(Lb);
cout<<"请输入从第几个元素删除->";
cin>>n;
cout<<"请输入要删除多少个数据->";
cin>>m;
cout<<"请要b链表中呢个位置插入->";
cin>>j;
Delete(&La,&Lb,n,m,j);
return 0;
}
此代码运行的结果也与上面一致,同时我们也可以进行尾插方式插入,该代码中使用的是头插的方式将被删除的数据存入Lb链表之中因为代码在创建链表时使用的是尾插方式,所以这里我选择使用头插方式插入。