数据结构之链表相关操作(一)

数据结构之链表相关操作(一)

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值