题解

1 条题解

  • 0
    @ 2022-07-17 12:49:06
    /****************************************************
    * 名字: 双向循环链表                                *
    * 作者: JL                                            *
    * 完成日期: 2016.2.12                               *
    * 编译环境: GCC                                     *
    * 备注:本代码只用于教学使用                     * 
    ****************************************************/
    
    #include <stdio.h>
    #include <malloc.h>
    #include <stdlib.h>
    #include "iostream"
    using namespace std;
    #define MAXNUM 0x7fffffff
    #define MAXSCORE 100000
    
    typedef struct LNode {
        int num;//学号 
        char name[20];//姓名 
        double score;//成绩 
        struct LNode *prior; //前向指针 
        struct LNode *next;  //后项指针
    } LNode, *LinkList;
    
    // 2、测链表长度
    int ListLength_L(LinkList L)
    {
        int i;
        LinkList p = L->next;
        for(i=0,p=L;p->next!=L;p=p->next,i++);//空循环,只计数 ;i能从1开始吗? 
        return i;
    } 
    
    // 3、销毁链表
    void DestroyList_L(LinkList &L)//
    {
        LinkList p = L->prior->prior;
        for(L->prior==NULL;p;p=p->prior)//从后向前逐个销毁 
            free(p->next);
        free(L);
    }
    
    // 4、返回第pos个元素的地址
    LinkList ListGetElem(LinkList L, int pos)
    {
        LinkList e = NULL; //定义结点指针
        int len = ListLength_L(L);
        if(pos<0 || pos>len)return 0;  //位置不合法 ,思考为什么0也合法? 
        e = L; 
        for(int i=0;i<pos;i++,e=e->next);  //空循环体,只是把e定位到pos-1 
        return e;
    }
    
    // 1、创建一个空的双向循环链表 
    int InitList_L(LinkList &L)
    {
        if(L)DestroyList_L(L);//如果链表已存在,先销毁 
        L = (LinkList) malloc (sizeof (LNode));
        if (!L) return 1; // 存储分配失败
        L->num = MAXNUM; L->score = MAXSCORE;//表头空结点赋特殊值 
        memset(L->name,0,sizeof(L->name));
        L->prior = L;  // 双向循环链表只有表头空节点时,前向和后向 
        L->next = L;   // 指针都是指向自己的 
        return 0;
    }
    
    // 5、顺序输出链表
    void PrintList_L(LinkList L)
    {
        LinkList p = L->next;
        for(;p!=L;p=p->next)
            cout << p->num << ' ' << p->name << ' ' << p->score << endl;
    }
    
    // 6、在链表中t指向的元素之后插入元素
    int ListInsert_L(LinkList t, LNode e)
    {
        if(!t)return 1;//获取地址失败,返回 
        LinkList p = (LinkList) malloc (sizeof (LNode));
        if (!p) return 1; // 存储分配失败
        *p = e;             //结构体是可以直接赋值的 
        p->next = t->next;  t->next = p;  //后向指针链接修改 
        p->next->prior = p; p->prior = t; //前向指针链接修改
        
        return 0;
    }
    
    // 7、构造带数据的链表
    int CreateList_L(LinkList &L)
    {
        if(L)DestroyList_L(L);//如果链表已存在,先销毁
        InitList_L(L);      //初始化链表 
        int i,n;
        cin >> n;
        while(n--)
        {
            LinkList p = (LinkList) malloc (sizeof (LNode));
            if (!p) return 1; // 存储分配失败
            cin >> p->num >> p->name >> p->score;
            LinkList t = L->prior;
            p->next = t->next;  t->next = p;  //后向指针链接修改 
            p->next->prior = p; p->prior = t; //前向指针链接修改
        }
    }
    
    // 8、删除p指向的元素
    int ListDelete_L(LinkList p)
    {
        if (p->num==MAXNUM || !p) return 1;//判定删除位置是否合法,表头能删吗? 
        p->prior->next = p->next;    //后向指针链接修改
        p->next->prior = p->prior;  //前向指针链接修改
        free(p);            //销毁该元素 
        return 0;
    } 
    
    // 9、学号相等判定函数
    int CmpNum(LinkList pa, LinkList pb)
    {
        return pa->num == pb->num;
    }
    
    // 10、查找并返回地址,未找到返回表头空结点地址,利用外部函数判定
    LinkList LocateElem_L(LinkList L, LNode e, int (*cmp)(LinkList,LinkList))
    {
        LinkList p=L->next;  //p是查找指针 
        for(;p!=L;p=p->next)
            if(cmp(p,&e))break;//循环查找,找到推出循环 
        return p;               //返回找到元素的地址,或表头地址 
    }
    
    // 11、成绩小于判定函数
    int cmp(LinkList pa, LinkList pb)
    {
        return pa->score < pb->score;
    }
    
    // 12、有序合并链表
    int Merg_L(LinkList La, LinkList Lb, LinkList &Lc)
    {
        if(Lc)DestroyList_L(Lc);            //如果Lc不为空,销毁 
        if(InitList_L(Lc))return 1;         //初始化Lc 
        LinkList pa,pb,pc,t;                //定义指向三个链表元素的指针 
        LNode e;                            //定义一个结点变量,用于保存待插入学生数据 
        for(pa=La->next;pa!=La;pa=pa->next) 
        {
            e = *pa;                        //待插入数据赋给e 
            t = LocateElem_L(Lc,e,cmp)->prior; //查找e插入的位置,找到插入点前驱结点地址 
            ListInsert_L(t,e);              //插入e
        }
        for(pb=Lb->next;pb!=Lb;pb=pb->next)
        {
            e = *pb;
            t = LocateElem_L(Lc,e,cmp)->prior;
            ListInsert_L(t,e);
        }
    }
    
    int main()
    {
        LNode e;
        LinkList l[4]={0};
        LinkList t;
        freopen("twlist.in","r",stdin);
        freopen("twlist.out","w",stdout);
    
        int n;
        cin >> n;
        while(n--)
        {
            int x,y,pos;
            cin >> x;
            switch(x)
            {
                case 1: cin >> y;
                        PrintList_L(l[y]);
                        break;
                case 2: InitList_L(l[1]);
                        break;
                case 3: cin >> pos >> e.num >> e.name >> e.score;
                        ListInsert_L(ListGetElem(l[1],pos-1),e);
                        break;
                case 4: CreateList_L(l[2]);
                        break;
                case 5: cin >> pos;
                        ListDelete_L(ListGetElem(l[1],pos));
                        break;
                case 6: cin >> e.num;
                        t = LocateElem_L(l[1],e,CmpNum);
                        ListDelete_L(t);
                        break;
                case 7: Merg_L(l[1],l[2],l[3]);
                        break;
            }
        }
    
        return 0;
    }
    
  • 1

信息

ID
1309
难度
8
分类
链表 点击显示
标签
递交数
3
已通过
1
通过率
33%
上传者