一、实验目的 通过该实验,深入理解链表的逻辑结构、物理结构等概念,掌握链表基本操作的编程实现,熟练掌握C语言中指针的操作。和实验3对比,掌握线性结构两种不同存储方式的区别。 二、实验内容 编程实现链表的基本操作,最好用菜单形式对应各个操作,使其编程一个完整的小软件。注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值。 三、主要源代码
#include "iostream" using namespace std; int checkStatus=0; typedef int Status; typedef int ElemType; typedef struct LNode { ElemType data; struct LNode *next; }LNode,*LinkList; static LinkList L; void selectFunc(int _select); void InitList(LinkList &L); void DestoryList(LinkList &L); void ListLength(LinkList &L); void GetData(LinkList &L); void LocateData(LinkList &L); void PriorData(LinkList &L); void NextData(LinkList &L); void ListInsert(LinkList &L); void ListDelete(LinkList &L); void Travel(LinkList &L); void InitList_Sq(LinkList &L); void ClearList(LinkList &L); void main() { cout<<"*********************************************************"<<endl; cout<<"*************** 1.初始化或重置链表 ***************"<<endl; cout<<"*************** 2.销毁链表 ***************"<<endl; cout<<"*************** 3.链表中数据元素个数 ***************"<<endl; cout<<"*************** 4.所指位序的元素值 ***************"<<endl; cout<<"*************** 5.链表已存在元素的位序 ***************"<<endl; cout<<"*************** 6.请输入元素,求直接前驱 ***************"<<endl; cout<<"*************** 7.请输入元素,求直接后继 ***************"<<endl; cout<<"*************** 8.在第i个位置插入元素 ***************"<<endl; cout<<"*************** 9.删除第i个元素 ***************"<<endl; cout<<"*************** 10.输出所输入的链表元素 ***************"<<endl; cout<<"*************** 11.初始化并输入链表元素 ***************"<<endl; cout<<"*************** 12.清空链表 ***************"<<endl; cout<<"*************** 13.退出 ***************"<<endl; cout<<"*********************************************************"<<endl; int _select; while(1) { cout<<"请输入功能前面的数字代号:"; cin>>_select; if(!cin || _select==0 || _select>13) { cout<<"您输入的选项有误,请重新输入!"<<endl; cout<<endl; cin.clear(); cin.sync(); continue; } else { if(_select<0) { exit(1); } else { selectFunc(_select); } } cout<<endl; } system("pause"); } void selectFunc(int _select) { switch(_select) { case 1: { InitList(L); checkStatus=1; break; } case 2: { if(checkStatus==1) { DestoryList(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 3: { if(checkStatus==1) { ListLength(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 4: { if(checkStatus==1) { GetData(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 5: { if(checkStatus==1) { LocateData(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 6: { if(checkStatus==1) { PriorData(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 7: { if(checkStatus==1) { NextData(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 8: { if(checkStatus==1) { ListInsert(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 9: { if(checkStatus==1) { ListDelete(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 10: { if(checkStatus==1) { Travel(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 11: { InitList_Sq(L); checkStatus=1; break; } case 12: { if(checkStatus==1) { ClearList(L); } else { checkStatus=0; cout<<"尚未初始化链表,请先初始化!"<<endl; } break; } case 13: { ClearList(L); DestoryList(L); exit(1); break; } default: { cout<<"输入不合法,请重新输入!"<<endl; break; } } } void InitList(LinkList &L) { L=(LinkList)malloc(sizeof(LNode)); if(!L) { cout<<"初始化失败!"<<endl; } else { L->data=NULL; L->next=NULL; cout<<"初始化链表成功!"<<endl; } } void DestoryList(LinkList &L) { LinkList p,q; p=L; q=L->next; while(p->next!=NULL) { free(p); p=q; q=q->next; } free(p); cout<<"销毁成功!"<<endl; } void ListLength(LinkList &L) { LinkList p; p=L; for(int n=0;p->next!=NULL;n++) { p=p->next; } cout<<"链表中数据元素有"<<n<<"个"<<endl; } void GetData(LinkList &L) { LinkList p,q; int e,i=1; cout<<"请输入要获取元素值的位置:"; cin>>i; p=L; for(int n=0;p->next!=NULL;n++) { p=p->next; } if(i<1||i>n) { cout<<"输入的位置不合法!"<<endl; } else { q=L->next; int j=1; while(q&&j<i) { q=q->next; j++; } e=q->data; cout<<"第"<<i<<"个位置的元素值为:"<<e<<endl; } } void LocateData(LinkList &L) { LinkList p; ElemType e; cout<<"请输入要获取位置的元素值:"; cin>>e; p=L->next; int i=1; while(p&&p->data!=e) { p=p->next; i++; } if(!p) { cout<<"元素不存在链表中!"<<endl; } else { cout<<e<<"所在的位序是"<<i<<endl; } } void PriorData(LinkList &L) { LinkList p,q; ElemType e; cout<<"请输入要求取前驱的元素:"; cin>>e; int j=0; p=L->next; if(p->data==e) { cout<<e<<"是链表中的第一个元素,没有前驱!"<<endl; j=1; } else { q=p->next; for(int i=1;p->next!=NULL;i++) { if(q->data==e) { cout<<e<<"的前驱为"<<p->data<<endl; j=1; } p=p->next; q=q->next; } if(j!=1) { cout<<"该元素不存在链表中,请重新输入!"<<endl; } } } void NextData(LinkList &L) { LinkList p,r,s; ElemType e; cout<<"请输入要求取后继的元素:"; cin>>e; int j=0; p=L; for(int n=0;p->next!=NULL;n++) { p=p->next; } r=L->next; s=r->next; for(int i=1;r->next!=NULL;i++) { if(r->data==e) { cout<<e<<"的后继为"<<s->data<<endl; j=1; break; } r=s; s=s->next; } if(j==0) { cout<<"该元素没有后继!"<<endl; } } void ListInsert(LinkList &L) { int i,e; cout<<"请输入要插入元素的位置:"; cin>>i; cout<<"请输入要插入元素的数值:"; cin>>e; LinkList p,q; p=L; int j=0; while(p&&j<i-1) { p=p->next; ++j; } if(!p||j>i-1) { cout<<"输入的位置不合法!"<<endl; } else { q=(LinkList)malloc(sizeof(LNode)); q->data=e; q->next=p->next; p->next=q; cout<<"插入成功!"<<endl; } } void ListDelete(LinkList &L) { int i,e; cout<<"请输入要删除的位置:"; cin>>i; LinkList p,q; p=L; int j=0; while(p->next!=0&&j<i-1) { p=p->next; j++; } if(!(p->next)||j>i-1) { cout<<"输入的位置不合法!"<<endl; } else { q=p->next; p->next=q->next; e=q->data; free(q); cout<<"删除的元素值为:"<<e<<endl; } } void Travel(LinkList &L) { LinkList p; cout<<"建立的链表为:"<<endl; for(p=L->next;p!=NULL;p=p->next) { cout<<p->data<<endl; } } void InitList_Sq(LinkList &L) { L=(LinkList) malloc(sizeof(LNode)); if(!L) { cout<<"初始化失败!"<<endl; } else { LinkList p,q; q=L; L->data=NULL; L->next=NULL; int n; cout<<"请输入链表元素的个数:"; cin>>n; cout<<"请输入链表元素值:"; for(int i=1;i<=n;i++) { p=(LinkList)malloc(sizeof(LNode)); cin>>p->data; p->next=NULL;q->next=p; q=q->next; } cout<<"创建链表成功!"<<endl; } } void ClearList(LinkList &L) { LinkList p,q; if(L==NULL) { cout<<"链表为空!"<<endl; } p=L->next; while(p!=NULL) { q=p->next; free(p); p=q; } L->next=NULL; cout<<"清空链表成功!"<<endl; }四、参考界面 增加了一个 清空链表。 注:销毁链表时需要循环释放每个结点所占用的空间。 注:求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。