#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;
}
双向循环链表模板
最新推荐文章于 2022-11-30 10:18:25 发布