1 条题解
-
0Guest LV 0 MOD
-
0
/**************************************************** * 名字: 双向循环链表 * * 作者: 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