双向循环链表模板


#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值