数据结构之链表相关操作(一)
#include <iostream>
#include <cstdio>
using namespace std;
struct LNode{ //链表结点
int data;
LNode *next;
//LNode(int x):data(x),next(NULL){} //默认构造函数
};
void PrintL(LNode *head){ //打印链表,传入的包含头结点-1
head=head->next; //右移一个,不然连头结点-1都打印了
while(head){
cout<<head->data<<" ";
head=head->next;
}
cout<<endl;
}
bool FindElem(LNode* head,int val){ //查找值是否存在
while(head){
if(head->data==val){
return true;
}else head=head->next;
}
return false;
}
LNode* LocateElem(LNode* head,int val){ //按值查找结点,返回结点指针,否则返回空
LNode *cur=head;
while(cur){
if(cur->data==val){
return cur;
}else cur=cur->next;
}
return cur;
}
LNode* GetElem(LNode* head,int i){ //按序号查找结点值,返回第i个结点的指针,否则返回NULL。传入一个没有头结点的链表。
int pos=1;
while(head){
if(pos==i){
return head;
}else{
head=head->next;
pos++;
}
}
return NULL;
}
void InsertElem(LNode* head,int i,int val){ //在第i个位置上插入新结点
LNode *p,*s;
s=new LNode(); //新构造的结点s
s->data=val;
p=GetElem(head->next,i-1); //查找插入位置的前一个结点p
s->next=p->next;
p->next=s;
}
void DeleteElem(LNode* head,int i){ //删除第i个位置的元素
LNode *p,*q;
p=GetElem(head->next,i-1); //查找删除位置的前一个结点p
q=p->next; //设待删除结点为q
p->next=q->next;
delete(q);
}
LNode* DeleteVal(LNode* head,int val){ //删除给定值的结点。传入一个带有头结点的链表。
while(head&&head->data==val){
LNode*p=head;
head=head->next;
delete p;
}
LNode *p=head,*q=head; //p是快指针,q是慢指针
while(p){
if(p->data==val){
q->next=p->next; //让q指向 p的下一个结点
delete p;
p=q->next; //q的下一位置赋给p,这样p在q前。
}else{
q=p;
p=p->next;
}
}
return head;
}
int LengthList(LNode* head){ //求链表表长,也就是求其中结点数
int l=0;
while(head){
l++;
head=head->next;
}
return l;
}
LNode* ReverseList(LNode* head){ //链表逆序
LNode *p,*q,*t;
if(!head->next||!head->next->next) return head;
p=head->next; //head,p,q,t
q=p->next;
while(q){
t=q->next; //t因q而存在
q->next=p;
p=q;
q=t;
}
head->next->next=NULL;
head->next=p;
return head;
}
LNode* MergeList(LNode* head1,LNode* head2){ //两个链表升序合并
LNode* head=new LNode(),*p,*q,*r; //最终合并的链表头指针head,r是其移动指针;而p和q分辨是head1和head2的移动指针
p=head1->next;
q=head2->next;
r=head;
while(p&&q){
if(p->data<q->data){
r->next=p;
r=p;
p=p->next;
}else{
r->next=q;
r=q;
q=q->next;
}
}
if(p) r->next=p;
if(q) r->next=q;
return head;
}
LNode* DelDupnosave(LNode* head){ //传入没有头结点的链表,删除重复且一个不留
LNode* dup=new LNode(),*p,*q;
dup->data=-1;
dup->next=head;
p=dup;
while(p->next){
q=p->next;
while(q&&p->next->data==q->data) q=q->next;
if(p->next->next==q) p=p->next;
else p->next=q;
}
return dup; //返回一个有头结点的链表
}
LNode* DelDupsave(LNode* head){ //删除重复且留一个
LNode* dup=new LNode(),*p,*q;
dup->data=-1;
dup->next=head;
p=dup->next;
while(p->next){
q=p->next;
while(q->next&&q->data==p->data) q=q->next;
if(p->data==q->data) p->next=NULL;
else p->next=q;
p=q;
}
return dup;
}
void swapdata(int &a,int &b){ //交换函数,用于交换数值,这里主要考虑交换数据域且上机万一不让用swap()函数。
int temp=a;
a=b;
b=temp;
}
LNode* BubbleSort(LNode *head){ //链表的冒泡排序(交换数据域),冒泡,需要两层for循环
LNode *p,*q,*t;
if(!head||!head->next) return head;
for(p=head;p!=NULL;p=p->next){
for(q=head;q->next!=NULL;q=q->next){
t=q->next;
if(q->data>t->data) swapdata(q->data,t->data);
}
}
return head;
}
LNode* CopyList(LNode* head){ //复制建立链表(带头结点)
LNode *h=new LNode(),*p,*q,*t; //h为新链表头,p为遍历原链表的指针,q为新建结点,t为插入辅助指针
if(!head||!head->next) return NULL;
h->data=-1;
t=h;
for(p=head->next;p!=NULL;p=p->next){
q=new LNode();
q->data=p->data;
t->next=q;
t=q;
}
return h;
}
LNode* GetKfromend(LNode* head,int k){
LNode *p=head,*q=head; //快指针p和紧随而来的慢指针q
while(k--){ //让p先跑k步
p=p->next;
}
while(p&&q){ //p和q同时向后遍历
p=p->next;
q=q->next;
}
return q;
}
int main(){
int n;
cin>>n;
LNode* head=new LNode(),*p,*q,*h,*le,*ge,*rl,*h2,*h3,*dns,*ds,*bs,*dt,*gk;
head->data=-1; //头结点默认值-1
p=head; //令p指向头结点(把头结点的指针赋给p)
while(n--){ //尾插法建链表
int temp;
cin>>temp;
q=new LNode(); //新建q结点
q->data=temp;
p->next=q; //p指向q
p=q; //再将p移向q(即把q赋给p)
}
cout<<"1.打印链表1:";
PrintL(head);
h=CopyList(head); //LNode 返回类型的函数,需要用一个指针来接收它
cout<<"15.打印复制链表1:";
PrintL(h);
cout<<"2.输入要查找的值a(是否存在):"<<endl;
int a;
cin>>a;
if(FindElem(head,a)){
cout<<"2.YES"<<endl;
}else cout<<"2.NO"<<endl;
cout<<"3.输入要查找的值b(返回指针):"<<endl;
int b;
cin>>b;
le=LocateElem(head,b);
cout<<le->data<<endl;
cout<<"4.输入要查找的序号i(第i个并返回指针):"<<endl;
int i;
cin>>i;
ge=GetElem(head,i+1);
cout<<ge->data<<endl;
cout<<"5.输入要插入的位置ie和插入值val:"<<endl;
int ie,val;
cin>>ie>>val;
InsertElem(head,ie,val);
cout<<"打印插入后的链表1:";
PrintL(head);
cout<<"6.输入删除的第de个位置的元素:"<<endl;
int de;
cin>>de;
DeleteElem(head,de);
cout<<"打印删除第de个位置后的链表1:";
PrintL(head);
cout<<"7.输入删除给定值dv的结点:"<<endl;
int dv;
cin>>dv;
dt=DeleteVal(head,dv);
cout<<"打印删除给定值后的链表1:";
PrintL(dt);
cout<<"8.显示链表结点数(包含隐藏的头结点):"<<LengthList(head)<<endl;
cout<<"9.显示逆序链表:"<<endl;
rl=ReverseList(head);
PrintL(rl);
h2=CopyList(head);
h3=CopyList(head);
cout<<"打印复制链表2:";
PrintL(h2);
cout<<"打印复制链表3:";
PrintL(h3);
dns=DelDupnosave(h2->next);
ds=DelDupsave(h3->next);
cout<<"11.打印删除重复不留一个链表2:";
PrintL(dns);
cout<<"12.打印删除重复只留一个链表3:";
PrintL(ds);
bs=BubbleSort(head);
cout<<"14.打印冒泡排序链表1:";
PrintL(bs);
cout<<"10.输入新链表的结点个数m:"<<endl;
int m;
cin>>m;
LNode* head1=new LNode(),*p1,*q1,*mg;
head1->data=-1;
p1=head1;
while(m--){ //尾插法建新链表
int temp;
cin>>temp;
q1=new LNode();
q1->data=temp;
p1->next=q1;
p1=q1;
}
cout<<"打印新链表head1:";
PrintL(head1);
mg=MergeList(h,head1);
cout<<"打印合并链表mg(链表1+链表hea1):";
PrintL(mg);
cout<<"16.输入k,查找倒数第k个结点值:"<<endl;
int k;
cin>>k;
gk=GetKfromend(mg,k);
cout<<gk->data<<endl;
return 0;
}