双向链表实验报告

合集下载

循环双链表实验报告

循环双链表实验报告

南京工程学院实验报告课程名称数据结构与算法实验实验项目名称线性表实验学生班级软件工程161 实验学生姓名潘登学号 202161024 实验时间 2017.11.2 实验地点图书馆A406实验成绩评定指导教师签字年月日一、实验目的和要求实验目的:验证教材中线性表链式存储结构的基本操作,设计并实现指定操作的算法,并做算法分析。

实验要求:①使用Java语言,采用泛型类;②争取最佳的算法效率(一次遍历)。

所有算法不能调用size()求元素个数后再操作。

③各类的成员方法,不改变参数list引用的链表,插入结点等操作都是深拷贝。

④声明返回各类对象(如SinglyList<T>)的成员方法,不改变调用者(this),this深拷贝。

⑤讨论各链表浅拷贝与深拷贝的差别,画出示意图。

二、实验题目2-145.void replaceAll(DoublyList<T>pattern,DoublyList<T>list)//替换所有与pattern匹配的子表为list三、实验方法与步骤(需求分析、算法设计思路、流程图等)需求分析:1.在target链表中寻找与pattern链表匹配的子联表2.用list链表替换该子联表3.过程简洁,效率高,一次遍历算法设计思路:先利用循环寻找到与pattern匹配的子联表,若无,则跳过该成员函数,若有,则以list链表为原型的循环双链表list2(构造循环双链表的效率更高),最后将list2整体替换子链(节省删除链表时间),同时list2变为空链表流程图:四、实验原始纪录(源程序、数据结构等)节点类public class DoubleNode<T>{public T data;public DoubleNode<T> prev,next;public DoubleNode(T data,DoubleNode<T> prev,DoubleNode<T> next)//创建节点public DoubleNode()//创建空节点public String toString()//输出节点元素}双链表类public class DoublyList<T> extends DoubleNode<T>{public DoubleNode<T> head;//头结点public DoublyList()//创建空链表public boolean isEmpty()//判断是否为空public int size()//长度 //以递归方式{return size(this.head.next);}private int size(DoubleNode<T> p){if(p!=null)return 1+size(p.next);elsereturn 0;}public DoubleNode<T> insert(int i,T x)//中间插入public DoubleNode<T> insert (T x)//尾插入public String toString()//输出链表}循环双链表类public class CirDoublyList<T> extends DoublyList<T>{public DoubleNode<T> head;public CirDoublyList()//创建空链表public CirDoublyList(DoublyList<T> list)//将list的数据拷贝到一个新的循环双链表{this.head=new DoubleNode<T>();this.head.prev=this.head;this.head.next=this.head;DoubleNode<T> L=list.head.next;while(L!=null){insert(L.data);L=L.next;}}public boolean isEmpty()//判断是否为空public int size()//长度以递归方式private int size(DoubleNode<T> p)public DoubleNode<T> insert(int i,T x)//中间插入public DoubleNode<T> insert(T x)//尾插入public void replaceAll(DoublyList<T> pattern, DoublyList<T> list)//用list 替换pattern{DoubleNode<T> T1=this.head.next;DoubleNode<T> p=T1;DoubleNode<T> q=pattern.head.next;while(p!=this.head&&q!=null&&p.data.equals(q.data))//匹配pattern链表{p=p.next;q=q.next;}if(q==null){CirDoublyList<T> list2=new CirDoublyList<T>(list);//创建list的循环双链表T1.prev.next=list2.head.next;list2.head.next.prev=T1.prev;p.prev=list2.head.prev;list2.head.prev.next=p;}}public String toString()//正序输出public String toPreviousString()//反序输出}主函数类import java.util.Scanner;public class SeqMain{public static void main(String[] args){CirDoublyList<String> target=new CirDoublyList<String>();DoublyList<String> pattern=new DoublyList<String>();DoublyList<String> list=new DoublyList<String>();int i;String ch;System.out.print("请输入target链表:");String str1=new Scanner(System.in).nextLine();for(i=0;i<str1.length();i++){ch=str1.substring(i, i+1);target.insert(ch);}System.out.print("请输入pattern链表:");String str2=new Scanner(System.in).nextLine();for(i=0;i<str2.length();i++){ch=str2.substring(i, i+1);pattern.insert(ch);}System.out.print("请输入list链表:");String str3=new Scanner(System.in).nextLine();for(i=0;i<str3.length();i++){ch=str3.substring(i, i+1);list.insert(ch);}target.replaceAll(pattern, list);System.out.println(target.toString());}}五、实验结果及分析(计算过程与结果、数据曲线、图表等)实验结果展示:六、实验总结与思考本实验是对链表的比较基础的运用(链表的查找,删除,插入)以及熟悉递归算法,算法本身并不难实现,难点在于算法的效率要高,可读性要强,这也是所有代码需要注意的,要做到每个指针都尽到最大的利用。

双向链表的算法设计与实现实验报告

双向链表的算法设计与实现实验报告

数学与计算科学学院实验报告
实验项目名称双向链表的算法设计与实现
所属课程名称__数据结构A
实验类型设计型
实验日期__
班级信计1402
学号201453100214
姓名俞凯烨
成绩
【实验小结】(收获体会)
附录1:源程序
附录2:实验报告填写说明
1.实验项目名称:要求与实验教学大纲一致。

2.实验目的:目的要明确,要抓住重点,符合实验教学大纲要求。

3.实验原理:简要说明本实验项目所涉及的理论知识。

4.实验环境:实验用的软、硬件环境。

5.实验方案(思路、步骤和方法等):这是实验报告极其重要的内容。

概括整个实验过程。

对于验证性实验,要写明依据何种原理、操作方法进行实验,要写明需要经过哪几个步骤来实现其操作。

对于设计性和综合性实验,在上述内容基础上还应该画出流程图、设计思路和设计方法,再配以相应的文字说明。

对于创新性实验,还应注明其创新点、特色。

6.实验过程(实验中涉及的记录、数据、分析):写明具体实验方案的具体实施步骤,包括实验过程中的记录、数据和相应的分析。

7.实验结论(结果):根据实验过程中得到的结果,做出结论。

8.实验小结:本次实验心得体会、思考和建议。

9.指导教师评语及成绩:指导教师依据学生的实际报告内容,给出本次实验报告的评价。

双向链表报告

双向链表报告

数据结构实验报告实验名称:双向链表1.实验要求根据线性表的抽象数据类型定义,选择下面任意种链式结构实现线性表,并完成线性表基本功能。

双向链表1.构造:使用头插法尾插法两种方式。

2.插入:要求建立的链表按照关键字从小到大有序3.删除4.查找5.获取链表长度6.销毁7.编写main()函数测试线性表的正确性。

2. 程序分析2.1 存储结构存储结构:双向链表结构2.2 关键算法分析1.关键算法:(1)构造函数:首先运用冒泡排序法进行排序,操作将输入的数据排序,然后逐一将各个数据存放到各个节点之中。

(2)查找操作:形参为查找位数,从头遍历链表进行逐个节点查找,//p=p->next;最后返回值为所查找的节点的地址。

(3)插入操作:建立新节点,运用后插操作,根据所插入的数据的大小自动找到所需插入的位置,并进行后插操作,将该节点插入到查找数字之后。

(4)删除:查找得到被删除节点的前一个节点将该节点的next指针跳过该节点指向被删除节点的下一个节点2.算法步骤:1.插入操作:s->data=x;s->next=p->next;s->prior=p;p->next=s;p->next->prior=s后插(1)将数据值赋给节点数据域(2)将s节点的next指向p节点的下一个节点(3)s的前驱指针指向p(4)p的next指针指向s(5)p的下一个节点的前驱指针指向s2.删除操作:p=Get(i-1);Node<T>*q=p->next;p->next=q->next;q->next->prior=p;T x=q->data;(1)查找得到所删除节点的前一个节点(2)创建新的节点指向将被删除的节点(3)查找所的节点的next指针指向被删除节点的下一个节点(4)将被删除节点的下一个节点的前驱指针指向查找所得节点3. 程序运行结果1.主函数流程2.(1)插入时:首先自动的判断所需输入数字的位置然后建立新的节点,然后进行后插入操作。

双向链表排序实验报告

双向链表排序实验报告

双向链表排序实验报告陈祎智实验报告<2> 1. 问题描述: 双向链表的排序。

要求:输入一个双向链表,显示些双向链表并对此双向链表排序2.课题分析(结构图):3.数据结构的设计: typedef struct node { int info;struct node *llink,*rlink;}NODE; 双向链表的排序双向链表存储结构快速排序定义输入数据结点4.流程图5.源程序:#include<iostream.h> #include<stdlib.h> #include <stdio.h> 开始创建链表初始化链表从中间分成两部排序链表插入 10 个值输出排序链表终止typedef struct Link/*双向链表结构体*/ {int data;struct Link *lift;struct Link *right; }linkx,*linky; linky Init();/*建立双向链表*/ void PrLink(linky p);/*输出双向链表*/ linky Sort(linky head);/*对双向链表排序*/ linky S head,linky one,linky two);/*任意交换双向链表两个结点的地址*/ void main(void) {linky head;head=Init();head=Sort(head);PrLink(head); } linky (Init())/*建立链表*/ {linky p,q,head;int n=0;head=p=q=(linky)malloc(sizeof(linkx));printf(“排序前的链表: “);scanf(“%d“,&amp;p->data);/*输入数据*/head->lift=NULL;n++;while(n!=10)/*一直输入到规定的数字个数停止*/ {q=p;p=(linky)malloc(sizeof(linkx));scanf(“%d“,&amp;p->data);/*输入数据*/q->right=p;p->lift=q;n++; }p->right=NULL;return(head); } linky S head,linky one,linky two)/*任意交换两个结点*/ {linky temp;if(one->lift==NULL&amp;&amp;two->right==NULL)/*首和尾巴的交换*/{if(one->right==two)/*只有两个结点的情况下*/{two->right=one;two->lift=NULL;one->lift=two;one->right=NULL;head=two;}else/*有间隔的首尾交换*/{one->right->lift=two;two->lift->right=one;two->right=one->right;one->lift=two->lift;two->lift=one->right=NULL;head=two;/*尾结点成为头结点*/}}else if(two->right==NULL)/*尾和任意一个交换*/ {if(one->right==two)/*交换最后两个结点*/{one->lift->right=two;two->lift=one->lift;two->right=one;one->lift=two;one->right=NULL;}else/*和前面其他结点交换*/{temp=two->lift;temp->right=one;one->lift->right=two;one->right->lift=two;two->lift=one->lift;two->right=one->right;one->lift=temp;one->right=NULL;}}else if(one->lift==NULL)/*头和任意一个交换*/ {if(one->right==two)/*交换头两个结点*/{two->right->lift=one;one->right=two->right;one->lift=two;two->right=one;two->lift=NULL;head=two;}else/*头结点和后面其他结点交换*/{temp=one->right;temp->lift=two;one->lift=two->lift;one->right=two->right;two->lift->right=one;two->right->lift=one;two->right=temp;two->lift=NULL;head=two;/*交换的结点成为头结点*/}}else/*当中的任意两个交换*/{if(one->right==two)/*交换连在一起的两个结点*/ {temp=one->lift;one->lift->right=two;one->right->lift=two;one->lift=two;one->right=two->right;two->right->lift=one;two->right=one;two->lift=temp;else/*交换隔开的两个结点*/{one->lift->right=two;one->right->lift=two;one->lift=two->lift;temp=one->right;one->right=two->right;two->lift->right=one;two->right->lift=one;two->right=temp;two->lift=one->lift;}}return(head); } linky Sort(linky head)/*对链表排序*/ {linky i,j,t,p;int max;p=head;for(i=p;i->right!=NULL;i=i->right)/*用选择法的思想对这些结点排序*/max=i->data;for(j=i->right;j!=NULL;j=j->right)if(j->data<max){max=j->data;t=j;}if(max!=i->data)/*假如没有找到比 i 小的结点*/{head=S);/*因为最终返回的是头结点,而头结点又有可能变化,所以每次头结点返回*/i=t;}}return(head); } void PrLink(linky p)/*输出链表*/ { linky q;printf(“排序后: “);do{q=p;printf(“%d “,p->data);p=p->right;free(q);/*释放输出结点*/}while(p!=NULL);}6.调试记录:第一次输入 136 134 158 123 197 124 156 170 103 101 实现排序第二次调试输入 12367 15842 12564 13729 49875 1546 15423 15794 54612 15437.软件说明程序调试运行成功后,排序前随机输入十个不同的数值,快速排序后将由小到大输出这十个数值的排序。

数据结构实验报告双链表

数据结构实验报告双链表

级数据结构实验报告实验名称:实验1 线性表学生姓名:班级:班内序号:学号:日期:1.实验要求1根据线性表的抽象数据类型的定义,选择下面任一种链式结构实现线性表,并完成线性表的基本功能。

1、双链表线性表的基本功能:1、构造:使用头插法、尾插法两种方法2、插入:要求建立的链表按照关键字从小到大有序3、删除4、查找5、获取链表长度6、销毁7、其他:可自行定义3编写测试main()函数测试线性表的正确性。

、4必须要有异常处理,比如删除空链表时需要抛出异常;5保持良好的编程的风格:代码段与段之间要有空行和缩近标识符名称应该与其代表的意义一致函数名之前应该添加注释说明该函数的功能关键代码应说明其功能递归程序注意调用的过程,防止栈溢出2. 程序分析2.1 存储结构2.2 关键算法分析 1.头插构造(一),自然语言1为将要插入的元素建立一个结点 2将结点连入头结点与原第二结点之间 (二),伪代码1初始化一个空链表2 为每个数组元素建立一个结点3将元素插进头结点与原第一结点间并连接上前后结点 4将原第一结点与头结点之间的连接断掉并连接到此元素上 (三),示意图first(b) 非空双循环链表 图2-19 双循环链表示意图(a) 空双循环链表图2-21双链表头插示意图(四),时间复杂度为O(1)2插入(一),自然语言1依次向后扫描直到目标位置,如果目标位置超出范围则抛出错误2更改目标位置前后指针,使插入元素连接进链表(二),伪代码1 定义工作指针p,计数器j清零2 执行下列操作,直到p超出链表范围或指向第i-1个结点2.1工作指针p后移;2.2j加1;3 更改目标位置的前后链接,连接上目标元素(三),具体代码template<class T>void LinkList<T>::Insert(int i,T x){Node<T> *p=first; int j=0;while(j<i-1){p=p->next;if(p==first)throw"x异常";j++;}{Node<T> *s=new Node<T>;s->data=x; s->next=p->next;s->prior=p;p->next->prior=s;p->next=s; //将元素链接在链表中}}(四),示意图双链表插入操作示意图(五),时间复杂度为O(n)3.删除(一),自然语言1依次向后扫描直到目标位置,如果目标位置超出范围则抛出错误2将目标元素删除(二),伪代码1 定义工作指针p,计数器j清零2 工作指针p后移2.1若p超出链表范围则抛出异常2.2 将p结点元素赋予x2.3 将p前驱后继从链表上摘下并将前驱后继相连2.4 释放被删除结点2.5返回x(三),具体代码template<class T>T LinkList<T>::Delete(int i){Node<T> *p=first;int j=0,x;while(j<i){p=p->next;if(p==first)throw"位置异常";//工作指针超过队尾则异常j++; //将工作指针移动到需删除元素的位子}if(p->next==first) cout<<"位置异常"<<endl;else{Node<T> *q=p;x=q->data;(p->prior)->next=p->next;(p->next)->prior=p->prior; //使该结点前后相连delete q; //删除该结点return x;}}(四)图2-22 双链表删除操作示意图(五),时间复杂度为O(n)2.3 其他3. 程序运行结果主函数流程自然语言1.定义a,b两个数组2. a,b分别头插尾插赋予list1 ,2两个双链表并输出3.获取List2中第二个节点4.在list2第二位插入8并输出List25.查找List2中3所在位置6.获取List2链表长度7.删除list2中第三个节点并输出执行结果4. 总结在这次实验中,我不仅更加深刻的了解了线性表表的结构,关于前驱,后继在表中的作用,与表中元素的联系,插入删除等操作的具体过程与使结构上发生的变化,查找,替换等操作的原理,而且对模板类这个上学期尚未学到的内容有了一个较为初步的认识。

链表合并实验报告

链表合并实验报告

《数据结构》实验报告◎实验题目: 实现两个有序循环链表的合并◎实验目的:掌握链表的建立、遍历以及数据的插入,加深对链表的理解。

◎实验内容:设A与B分别为两个带有头结点的有序循环链表(所谓有序是指链接点按数据域值大小链接,本题不妨设按数据域值从小到大排列),list1和list2分别为指向两个链表的头指针。

请写出将这两个链表合并为一个带头结点的有序循环链表的算法。

一、需求分析1、输入:该实验需要建立循环链表,以及读入数据,输出数据,并实现合并。

该链表输入为整数形式,输入值的范围为整个整数域。

2、输出:而输出的形式为整数。

3、程序功能:该程序实现了循环链表的建立,读入和输出数据,主要功能为实现了两个有序循环链表的合并。

4、程序执行命令:(1)创建链表(2)输入数据(3)合并链表(4)输出合并后链表(5)结束5、测试数据:假设第一个链表的输入数据个数为5,其分别为1、3、5、7、9,第二个链表的输入数据个数为3个,其分别为7、9、10,则合并后应输出结果:1 3 5 7 7 9 9 10。

二概要设计为了实现上述操作,应以单向循环链表为存储结构。

本程序的主程序的流程为:本程序的调用函数有创建链表函数create,输出函数displist,以及合并函数add三个模块,其中这三个函数都在主函数中被调用,三个调用函数为平行关系。

三详细设计1.元素类型,结点类型和指针类型:typedef int elemtype;typedef struct lnode{elemtype data;struct lnode *next;}linklist;linklist *s,*r;linklist *list1,*list2,*list3; 2.每个模块的分析:(1)主程序模块:main(){linklist *l1,*l2,*l3;int i,x,n;printf("请输入要建立的链表节点个数:\n");scanf("%d",&n);create(l1,n);displist(l1);getch();printf("请输入要建立的链表节点个数:\n");scanf("%d",&n);create(l2,n);displist(l2);getch();add(l1,l2,l3);printf("合并后链表:\n");displist(l3);getch();return 0;}(2)链表创建并输入数据create(linklist *&l,int n){linklist *s,*r;int i;l=(linklist *)malloc(sizeof(linklist));l->next=NULL;r=l;for(i=0;i<n;i++){s=(linklist *)malloc(sizeof(linklist));printf("\n请输入新节点数据:\n");scanf("%d",&s->data) ;r->next=s;r=s;}r->next=l->next;}(3)数据输出displist(linklist *l){linklist *p=l->next;do{printf("%5d",p->data);p=p->next;}while(p!=l->next);printf("\n");}(4)链表合并add(linklist *l1,linklist *l2,linklist *&l3){linklist *list1,*list2,*list3;l3=(linklist *)malloc(sizeof(linklist));l3->next=NULL;list3=l3;list1=l1->next;list2=l2->next;do{if(list1->data<=list2->data){list3->next=list1;list1=list1->next;list3=list3->next;}else{list3->next=list2;list2=list2->next;list3=list3->next;}} while(list3->next!=l1->next&&list3->next!=l2->next);if(list3->next==l2->next)while(list3->next!=l1->next){list3->next=list1;list3=list1;list1=list1->next;}elsewhile(list3->next!=l2->next){list3->next=list2;list3=list2;list2=list2->next;}list3->next=l3->next;}(5)函数调用关系图main()create()displist()add()diaplist()3.完整的程序:(见源文件).四使用说明、测试分析及结果1.程序使用说明:(1)本程序的运行环境为VC6.0。

数据结构实验五:链表实验

数据结构实验五:链表实验

一,实验题目实验五:假设有一个单向循环链表,其结点包含三个域:data,pre和next,其中data为数据域next为指针域,其值为后继结点的地址,pre也为指针域,其初值为空(null),试设计算法将此单向循环链改为双向循环链表。

二,问题分析本程序要求将一个包含三个域:data,pre和next,其中data为数据域next为指针域,其值为后继结点的地址,pre也为指针域的单向循环链表改为双向循环链表。

完成这些问题需要解决的是空链表的生成,链表元素的输入和输出,将单向链表改为双向链表等。

1,数据的输入形式和输出形式:单链表的元素均为int型,输出的单链表元素也为int型。

输出链表指针所指向的前一个或后一个链表元素时,选择1或2。

2,结果的输出形式:首先输出单链表的元素,将单链表转换为双向链表后,输出p指针所指的前一个或后一个链表元素。

3,测试数据:(1)输入的单链表元素为:23,553,87,0;(2)输入的单链表元素为:34,7650;三,概要设计1,为了实现上述程序功能,需要:(1)构造一个空的单链表L;(2)逐个输入单链表元素;(3)输出单链表元素;(4)将单链表转换为双向链表;(5)进行简单的双向链表功能测试Array 2,本程序包含5个函数:(1)主函数:main();(2)建立空链表函数:creatnull();(3)输入单链表元素函数:input();(4)转换为双向循环链表函数:setdouble(5)单链表输出函数:display();个函数间的关系如右图所示:四,详细设计1,链表的结构类型定义:typedef struct dnode{int data;struct dnode *pre,*next;}dlinklist;2,建立空链表伪代码:dlinklist *creatnull(){dlinklist *L;L=(dlinklist*)malloc(sizeof(dlinklist));L->next=NULL;L->pre=NULL;L->data=NULL;return L;}3,建单链表伪代码:dlinklist* input(dlinklist *L,int x){dlinklist *s,*r;r=L->next; s=creatnull(); s->data=x; L->next=s; s->next=r;return L;}4,将单链表转换为双向循环链表的伪代码:dlinklist *setdouble(dlinklist *L){dlinklist *s,*t; s=L; t=L->next;while(t!=NULL){t->pre=s; s=s->next; t=t->next;}return L;}五,源程序#include "stdio.h"#include "malloc.h"typedef struct dnode{ //链表的结构类型定义int data; //数据域struct dnode *pre,*next;}dlinklist;dlinklist *creatnull(){ //建立空链表,即建立空结点dlinklist *L;L=(dlinklist*)malloc(sizeof(dlinklist)); //为新节点申请空间L->next=NULL;L->pre=NULL;L->data=NULL; //置空return L;}dlinklist* input(dlinklist *L,int x) //头插法建单链表{dlinklist *s,*r;r=L->next; //将L指向的下一个节点赋值给rs=creatnull(); //建立空点结s->data=x; //将x值赋给新建结点的data域L->next=s; //将s赋值给L指向的下一个结点s->next=r; //将r赋给s所指向的下一个结点,完成插入return L;}dlinklist *setdouble(dlinklist *L){ //将单链表转换为双向循环链表dlinklist *s,*t;s=L;t=L->next;while(t!=NULL){t->pre=s;s=s->next;t=t->next;}return L;}void display(dlinklist *k) //输出顺序表中数据{k=k->next;while(k!=NULL){printf("%d ",k->data);k=k->next;}}void main(){dlinklist *p,*q; //定义两个指针型变量p,qint x,i=0;p=creatnull(); //建立空链表q=p; //使q也指向头结点printf("输入顺序表的元素,(输入0表示输入结束):\n");while(x!=0){p=input(p,x); //当x不等于0时,输入链表元素xscanf("%d",&x);}printf("输入的顺序表元素为:\n");p=setdouble(p); //将单链表转换为双向循环链表display(p); //输出链表表元素do{printf("\n");printf("1,输出下一个数据:\n");printf("2,输出上一个数据:\n");printf("请选择要输出的是顺序表元素的上一个还是下一个元素:\n");scanf("%d",&i);switch(i) //选择语句{case 1: //当i为1时,输出q指针所指的下一个链表元素q=q->next;if(q!=NULL)printf("\t链表元素为%d\n",q->data);else{printf("\t为表尾元素");q=p;}break;case 2: //当i为2时,输出q指针所指的前一个链表元素q=q->pre;if(q->pre!=NULL)printf("\t链表元素为%d\n",q->data);else{printf("\t为表头元素");q=p;}break;}}while(1);}六,调试分析如下语句所示,当输入顺序表元素时,没有输入语句“scanf(“%d”,&x)“则输出的错误结果:即要输入的链表元素为54,43,23.但输出是却多出一个元素。

链表(单链表 双向循环)实验报告讲解

链表(单链表 双向循环)实验报告讲解

数据结构实验报告T1223-3-21余帅实验一实验题目:仅仅做链表部分难度从上到下1.双向链表,带表头,线性表常规操作。

2.循环表,带表头,线性表常规操作。

3.单链表,带表头,线性表常规操作。

实验目的:了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。

实验要求:常规操作至少有:1.数据输入或建立2.遍历3.插入4.删除必须能多次反复运行实验主要步骤:1、分析、理解给出的示例程序。

2、调试程序,并设计输入数据,测试程序的如下功能:1.数据输入或建立2.遍历3.插入4.删除单链表示意图:headhead head 创建删除双向循环链表示意图:创建程序代码://单链表#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node *next;};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;searchp = searchp->next;count++;}searchp->next = NULL;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>=count)return range_error;node *newnodep=new node,*searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next=followp->next; //注意此处的次序相关性followp->next=newnodep;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp;if(empty())return underflow;searchp = headp->next;cout<<"连表中的数据为:"<<endl;while(searchp!=NULL){cout<<searchp->data<<" ";searchp = searchp->next;}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonfacevoid clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}/* 功能:用双向循环链表存储数据1.创建链表2.增加结点3.删除结点4.遍历链表制作人:余帅内容:239行*/#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node * next; //指向后续节点node * pre; //指向前面的节点};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;headp->pre = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;headp->pre = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;newnodep->pre = searchp;searchp = searchp->next;count++;}searchp->next = headp;headp->pre = searchp;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>count+1)return range_error;node *newnodep=new node;node *searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next = searchp;searchp->pre = newnodep;followp->next = newnodep;newnodep->pre = followp;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句searchp->next->pre = followp;delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp1,*searchp2;if(empty())return underflow;searchp1 = headp;searchp2 = headp;cout<<"连表中的数据为:"<<endl;cout<<"从左至右读取:";while (searchp1->next!=headp ) {searchp1 = searchp1 ->next;cout << searchp1->data<<" ";}cout<<endl;cout<<"从右至左读取:";while (searchp2->pre!=headp ) {searchp2 = searchp2 ->pre;cout << searchp2->data<<" ";}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonface void clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}运行结果:1.创建链表:2.增加结点3.删除结点心得体会:本次实验使我们对链表的实质了解更加明确了,对链表的一些基本操作也更加熟练了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

13软工转本1 钱剑滨实验报告双向链表实验报告信息工程系 13软工转本1 日期 2016年03月12日姓名钱剑滨学号 13131116 电话一、实验内容编写关于双向链表操作的C语言程序,要求包含双向链表的创建(生成)、输出(遍历)、查找、任意位置插入、有顺序插入、删除、等。

二、实验步骤1.分析操作所需思路,熟练运用单链表的各种特点。

2.编写程序,利用函数特性进行操作。

3.运行程序,纠正错误,对预测结果进行验证。

4.分析总结单链表的优缺点,并可以做到熟练掌握双向链表的各种操作。

三、设计概要1.本实验包含了7个函数:a)主函数main()b)创建链表函数Listcreate()c)数据输出函数Listprint()d)查找数据函数Listlocate()e)无序插入函数Listinsert_discretion ()f)有序插入函数Listinsert_orderg)删除数据函数Listdelete()2.明确函数的功能;a)Listcreate() 创建一个可控长度的斐波那契数列的双向链表。

b)Listprint() 将此链表中的数据全部输出。

c)Listlocate() 查找此链表中任意位置元素的值。

d)Listinsert_discretion ()向此链表的某个位置插入一组数据。

e)Listinsert_order() 向数列中插入一个数,使插入后的数列任然有序f)Listdelete() 将此链表的某个位置的一组数据删除。

四、程序设计1.函数前包含的头文件名、结点类型定义、全局变量和函数声明#include <stdio.h>#include <malloc.h>typedef struct number //定义结构体{struct number *prior;int num;struct number *next;}number;number *head; //定义全局变量头节点int k = 0; //k记录元素个数,防止溢出/*函数声明*/void Listcreate(); //建立链表void Listprint(); //全体输出void Listlocate(); //查找void Listinsert_discretion(); //任意位置插入void Listinsert_order(); //有顺序插入void Listdelete(); //删除2.主函数main()void main(){int select;printf("1、输入斐波那契数列的个数\n");printf("2、全部输出数列\n");printf("3、查找定位数列的元素\n");printf("4、添加数列元素\n");printf("5、插入顺序数列元素\n");printf("6、删除数列元素\n");printf("-------------------------------------\n");while (1){printf("请选择序号\n");scanf("%d", &select);switch (select){case 1: Listcreate(); break; //链表创建case 2: Listprint(); break; //全链表输出case 3: Listlocate(); break; //元素查找case 4: Listinsert_discretion(); break; //任意位置插入case 5: Listinsert_order(); break; //有顺序插入case 6: Listdelete(); break; //删除default: break;}}}3.创建链表函数Listcreate()void Listcreate() //建立链表{head = (number *)malloc(sizeof (number)); //开辟一个大小为number的内存空间给头节点head->next = NULL;head->prior = NULL;int a = 1,b = 1; //a、b为斐波那契数列的前两个元素int i;number *q;number *p = head; //p始终指向最后一个节点printf("输入元素的长度\n");scanf("%d",&i);/*给第一个元素赋值*/q = (number *)malloc(sizeof (number)); //开辟一个大小为number的内存空间给后面节点q->num = a;q->next = NULL; //新开辟的节点指向NULLp->next = q; //前一节点指向新开辟的节点q->prior = p; //开辟的节点前驱指向pp = p->next; //p指向新节点i = i - 1;k = k + 1;/*给第二个元素赋值*/q = (number *)malloc(sizeof (number));q->num = b;q->next = NULL;p->next = q;q->prior = p;p = p->next;i = i - 1;k = k + 1;/*给后续元素赋值*/while (i--)q = (number *)malloc(sizeof (number));q->num = (a+b);q->next = NULL;p->next = q;q->prior = p;p = p->next;a = a +b + b; //b = a - b; //将a+b的值付给b;b的值付给aa = a - b; //k = k + 1;}printf("链表建立成功\n");}4.数据输出函数Listprint()void Listprint() //全体输出{number *p = head->next;while (p != NULL){printf("%d ", p->num);p = p->next;}printf("\n");}5.查找数据函数Listlocate()void Listlocate() //查找{int i;number *p = head;printf("输入您要查询的元素位置\n");scanf("%d", &i);if ((i > k) || (i <= 0)){printf("查询的位置不存在\n");}else{while (i--){p = p->next;}printf("所查找数为%d\n", p->num);}}6.无序插入函数Listinsert_discretion()void Listinsert_discretion() //任意位置插入{int i;number *q;number *p = head;printf("输入您要插入哪个元素的后面\n");scanf("%d", &i);if ((i > k) || (i < 0)){printf("插入的位置不存在\n");}else{while (i--){p = p->next; //p最后指向要插入位置的前一个节点}q = (number *)malloc(sizeof (number));if (p->next == NULL) //插到末尾{q->next = NULL; //B的下一个元素指向空p->next = q; //p的下一个元素指向Bq->prior = p; //B的前驱指向p}else{q->next = p->next; //B的下一个元素指向p的下一个(两个不能反)p->next->prior = q; //p的下一个元素的前驱指向Bp->next = q; //p的下一个元素指向Bq->prior = p; //B的前驱指向p}printf("输入您要插入的数\n");scanf("%d", &(q->num));k = k + 1;}printf("插入成功\n");}7.有序插入函数Listinsert_order ()void Listinsert_order() //有顺序插入{number *q;number *p = head;q = (number *)malloc(sizeof (number));printf("输入您要插入哪个数\n");scanf("%d", &q->num);while (p->next){if (p->next->num >= q->num) //插在第一个比数大或等于的的数前{q->next = p->next;p->next->prior = q;p->next = q;q->prior = p;k = k + 1;break;}else{p = p->next;}}if (p->next == NULL) //插到末尾{q->next = NULL;p->next = q;q->prior = p;k = k + 1;}printf("插入成功\n");}8.删除数据函数Listdelete ()void Listdelete() //删除{int i;number *q;number *p=head;printf("输入您要删除哪个元素\n");scanf("%d", &i);if ((i > k) || (i <= 0)){printf("删除的位置不存在\n");}else{while (--i) //这里是先减再判断{p = p->next; //p指向被删除的元素的前一个元素}q = p->next; //q指向被删除的元素if (q->next == NULL) //删除最后一个元素{p->next = NULL;}else{p->next = q->next; //p的下一个元素指向q的下一个,即跳过被删除元素q->next->prior = p; //q的下一个元素的前驱指向p,也跳过被删除的元素}free(q); //清空删除元素k = k - 1;}printf("删除成功\n");}五、程序源码#include <stdio.h>#include <malloc.h>typedef struct number{struct number *prior;int num;struct number *next;}number;number *head; //定义全局变量头节点int k = 0; //k记录元素个数,防止溢出void Listcreate(); //建立链表void Listprint(); //全体输出void Listlocate(); //查找void Listinsert_discretion(); //任意位置插入void Listinsert_order(); //有顺序插入void Listdelete(); //删除void main(){int select;printf("1、输入斐波那契数列的个数\n");printf("2、全部输出数列\n");printf("3、查找定位数列的元素\n");printf("4、添加数列元素\n");printf("5、插入顺序数列元素\n");printf("6、删除数列元素\n");printf("-------------------------------------\n");while (1){printf("请选择序号\n");scanf("%d", &select);switch (select){case 1: Listcreate(); break;//链表创建case 2: Listprint(); break;//全链表输出case 3: Listlocate(); break; //元素查找case 4: Listinsert_discretion(); break; //任意位置插入case 5: Listinsert_order(); break; //有顺序插入case 6: Listdelete(); break; //删除default: break;}}}void Listcreate() //建立链表{head = (number *)malloc(sizeof (number)); //开辟一个大小为number 的内存空间给头节点head->next = NULL;head->prior = NULL;int a = 1,b = 1; //a、b为斐波那契数列的前两个元素int i;number *q;number *p = head; //p始终指向最后一个节点printf("输入元素的长度\n");scanf("%d",&i);q = (number *)malloc(sizeof (number)); //开辟一个大小为number的内存空间给后面节点q->num = a;q->next = NULL; //新开辟的节点指向NULLp->next = q; //前一节点指向新开辟的节点q->prior = p; //开辟的节点前驱指向pp = p->next; //p指向新节点i = i - 1;k = k + 1;q = (number *)malloc(sizeof (number));q->num = b;q->next = NULL;p->next = q;q->prior = p;p = p->next;i = i - 1;k = k + 1;while (i--){q = (number *)malloc(sizeof (number));q->num = (a+b);q->next = NULL;p->next = q;q->prior = p;p = p->next;a = a +b + b; //b = a - b; //将a+b的值付给b;b的值付给aa = a - b; //k = k + 1;}printf("链表建立成功\n");}void Listprint() //全体输出{number *p = head->next;while (p != NULL){printf("%d ", p->num);p = p->next;}printf("\n");}void Listlocate() //查找{int i;number *p = head;printf("输入您要查询的元素位置\n");scanf("%d", &i);if ((i > k) || (i <= 0)){printf("查询的位置不存在\n");}else{while (i--){p = p->next;}printf("所查找数为%d\n", p->num);}}void Listinsert_discretion() //任意位置插入{int i;number *q;number *p = head;printf("输入您要插入哪个元素的后面\n");scanf("%d", &i);if ((i > k) || (i < 0)){printf("插入的位置不存在\n");}else{while (i--){p = p->next; //p最后指向要插入位置的前一个节点}q = (number *)malloc(sizeof (number));if (p->next == NULL) //插到末尾{q->next = NULL; //B的下一个元素指向空p->next = q; //p的下一个元素指向Bq->prior = p; //B的前驱指向p}else{q->next = p->next; //B的下一个元素指向p的下一个(两个不能反)p->next->prior = q; //p的下一个元素的前驱指向Bp->next = q; //p的下一个元素指向Bq->prior = p; //B的前驱指向p}printf("输入您要插入的数\n");scanf("%d", &(q->num));k = k + 1;}printf("插入成功\n");}void Listinsert_order() //有顺序插入{number *q;number *p = head;q = (number *)malloc(sizeof (number));printf("输入您要插入哪个数\n");scanf("%d", &q->num);while (p->next){if (p->next->num >= q->num) //插在第一个比数大或等于的的数前{q->next = p->next;p->next->prior = q;p->next = q;q->prior = p;k = k + 1;break;}else{p = p->next;}}if (p->next == NULL) //插到末尾{q->next = NULL;p->next = q;q->prior = p;k = k + 1;}printf("插入成功\n");}void Listdelete() //删除{int i;number *q;number *p=head;printf("输入您要删除哪个元素\n");scanf("%d", &i);if ((i > k) || (i <= 0)){printf("删除的位置不存在\n");}else{while (--i) //这里是先减再判断{p = p->next; //p指向被删除的元素的前一个元素}q = p->next; //q指向被删除的元素if (q->next == NULL) //删除最后一个元素{p->next = NULL;}else{p->next = q->next; //p的下一个元素指向q的下一个,即跳过被删除元素q->next->prior = p; //q的下一个元素的前驱指向p,也跳过被删除的元素}free(q); //清空删除元素k = k - 1;}printf("删除成功\n");}六、测试结果1.最初运行程序时,有如下结果:2.在输入1后,创建长度为10的斐波那契数列,结果如下:3.在输入2后,显示数列,结果如下:4.在输入3后,进行查询操作后,结果如下:5.在输入4后,进行无序插入操作后,结果如下:6.在输入5后,进行有序插入操作后,结果如下:7.在输入6后,进行删除操作后,结果如下:8.输入其他数字的结果:七、总结反思刚做这个题目的时候发现自己结构体和链表学的太浅了,以前学得只是也不能很好的运用。

相关文档
最新文档