北京邮电大学 数据结构 实验一 带头结点的单链表构造
北京邮电大学 数据结构 实验一 带头结点的单链表构造

数据结构实验报告实验名称:实验1——单链表的构造学生姓名:XXXXNB班级:XXXX班内序号:学号:XXXX日期:XXXXX1.实验要求根据线性表的抽象数据类型的定义,完成带头结点的单链表的基本功能。
单链表的基本功能:1、构造:使用头插法、尾插法两种方法2、插入:要求建立的链表按照关键字从小到大有序3、删除4、查找5、获取链表长度6、销毁7、其他:可自行定义编写测试main()函数测试线性表的正确性。
2.程序分编程完成单链表的一般性功能如单链表的构造:使用头插法、尾插法两种方法插入:要求建立的链表按照关键字从小到大有序,删除,查找,获取链表长度,销毁用《数据结构》中的相关思想结合C++语言基本知识编写一个单链表结构。
本程序为使用方便,几乎不用特殊的命令,只需按提示输入即可,适合更多的用户使用。
2.1 存储结构单链表的存储结构:2.2 关键算法分析1.头插法自然语言描述:a.在堆中建立新结点b.将a[i]写入到新结点的数据域c.修改新结点的指针域d.修改头结点的指针域,将新结点加入链表中//在构建之初为了链表的美观性构造,进行了排序代码描述://头插法构造函数template<class T>LinkList<T>::LinkList(T a[], int n){for (int i = n - 1; i >= 1; i--)//冒泡排序,对数组进行从小到大排序{for (int j = 0; j < i; j++){if (a[j]>a[j + 1]){T t = a[j + 1];a[j + 1] = a[j];a[j] = t;}}}front = new Node < T >;//为头指针申请堆空间front->next = NULL;//构造空单链表for (int i = n - 1; i >= 0; i--){Node<T>*s = new Node < T >;//建立新结点s->data = a[i];//将a[i]写入新结点的数据域s->next = front->next;//修改新结点的指针域front->next = s;//修改头结点的指针域,将新结点加入到链表中}}2.尾插法自然语言描述:a.在堆中建立新结点b.将a[i]写入到新结点的数据域c.将新结点加入到链表中d.修改修改尾指针代码描述://尾插法构造函数template<class T>LinkList<T>::LinkList(T a[], int n){front = new Node < T > ;Node<T>*r = front;//命名一个新变量进行转换for (int i = 0; i < n; i++){Node<T>*s = new Node < T > ;s->data = a[i];r->next = s;r = s;}r->next = NULL;}时间复杂度:O(n)3.析构函数自然语言描述:a.新建立一个指针,指向头结点b.移动a中建立的指针c.逐个释放指针代码描述:template<class T>LinkList<T>::~LinkList()//析构函数,销毁链表{Node<T> * p = front;while(p){front = p;p = p->next;delete front;}}4.按位查找函数自然语言描述: a.初始化工作指针p和计数器j,p指向第一个结点,j=1b.循环以下操作,直到p为空或者j等于1b1:p指向下一个结点b2:j加1c.若p为空,说明第i个元素不存在,抛出异常d.否则,说明p指向的元素就是所查找的元素,返回元素地址代码描述:template<class T>Node<T>* LinkList<T>::Get(int i)//按位查找{Node<T> * p = front;int j=0;while(p){if(j<i){p = p->next;j++;}else break;}if(!p) throw"查找位置非法";else return p;}时间复杂度:O(n)5.按值查找函数自然语言描述:a.初始化工作指针p和计数器j,p指向第一个结点,j=1b.循环以下操作,找到这个元素或者p指向最后一个结点b1.判断p指向的结点是不是要查找的值,如果是,返回j;b2.否则p指向下一个结点,并且j的值加一c.如果找到最后一个结点还没有找到要查找的元素,返回查找失败信息代码描述:template<class T>int LinkList<T>::Locate(T x)//按值查找{Node<T> * p = front->next;int j = 1;while(p){if(p->data == x) return j;else{p = p->next;j++;}}return -1;}时间复杂度:O(n)6.插入函数自然语言描述:a.在堆中建立新结点b.将要插入的结点的数据写入到新结点的数据域c.修改新结点的指针域d.修改前一个指针的指针域,使其指向新插入的结点的位置代码描述:template<class T>void LinkList<T>::Insert(int i,T x)//插入函数{Node<T> * p = Get(i-1);if(p){Node<T> * s = new Node<T>;s->data = x;s->next = p->next;p->next = s;}else throw"插入位置非法";}时间复杂度:O(n)7.按位删除函数自然语言描述:a.从第一个结点开始,查找要删除的位数i前一个位置i-1的结点b.设q指向第i个元素c.将q元素从链表中删除d.保存q元素的数据e.释放q元素代码描述:template<class T>T LinkList<T>::Delete(int i)//删除函数{Node<T> *p = Get(i-1);Node<T> *q = p->next;T x=q->data;p->next = q->next;delete q;return x;}8.遍历打印函数自然语言描述: a.判断该链表是否为空链表,如果是,报错b.如果不是空链表,新建立一个temp指针c.将temp指针指向头结点d.打印temp指针的data域e.逐个往后移动temp指针,直到temp指针的指向的指针的next域为空代码描述:template<class T>void LinkList<T>::PrintList()//打印链表{Node<T> * p = front->next;while(p){cout<<p->data<<' ';p = p->next;}cout<<endl;}9.获取链表长度函数自然语言描述:a.判断该链表是否为空链表,如果是,输出长度0b.如果不是空链表,新建立一个temp指针,初始化整形数n为0c.将temp指针指向头结点d.判断temp指针指向的结点的next域是否为空,如果不是,n加一,否则return ne.使temp指针逐个后移,重复d操作,直到temp指针指向的结点的next 域为0,返回n代码描述:template<class T>int LinkList<T>::GetLength()//分析链表长度{Node<T> * p = front;int i=0;while(p){p = p->next;i++;}return i-1;}2.3 其他异常处理采用try catch 函数处理异常如在插入时的异常处理:template<class T>void LinkList<T>::Insert(int i, T x){Node<T>*p = front;if (i != 1) p = Get(i - 1);try{if (p){Node<T>*s = new Node < T > ;s->data = x;s->next = p->next;p->next = s;}else throw i;}catch (int i){cout << "插入到位置 " << i << " 处" << "为错误位置"<<endl;}}3. 程序运行结果主函数流程图:测试截图:初始化链表,菜单创建执行功能:4. 总结.调试时出现了一些问题如:异常抛出的处理,书中并未很好的提及异常处理,通过查阅资料,选择用try catch 函数对解决。
北邮数据结构实验报告

北邮数据结构实验报告摘要:本报告基于北邮数据结构实验,通过实际操作和实验结果的分析,总结和讨论了各实验的目的、实验过程、实验结果以及相关的问题和解决方法。
本报告旨在帮助读者了解数据结构实验的基本原理和应用,并为今后的学习和研究提供参考。
1. 实验一:线性表的操作1.1 实验目的本实验旨在掌握线性表的基本操作以及对应的算法实现,包括插入、删除、查找、修改等。
1.2 实验过程我们使用C++语言编写了线性表的相关算法,并在实际编程环境下进行了测试。
通过插入元素、删除元素、查找元素和修改元素的操作,验证了算法的正确性和效率。
1.3 实验结果经过测试,我们发现线性表的插入和删除操作的时间复杂度为O(n),查找操作的时间复杂度为O(n),修改操作的时间复杂度为O(1)。
这些结果与预期相符,并反映了线性表的基本特性。
1.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如插入操作的边界条件判断、删除操作时的内存释放等。
通过仔细分析问题,我们优化了算法的实现,并解决了这些问题。
2. 实验二:栈和队列的应用2.1 实验目的本实验旨在掌握栈和队列的基本原理、操作和应用,并进行实际编程实现。
2.2 实验过程我们使用C++语言编写了栈和队列的相关算法,并在实际编程环境下进行了测试。
通过栈的应用实现表达式求值和逆波兰表达式的计算,以及队列的应用实现图的广度优先遍历,验证了算法的正确性和效率。
2.3 实验结果经过测试,我们发现栈的应用可以实现表达式的求值和逆波兰表达式的计算,队列的应用可以实现图的广度优先遍历。
这些结果证明了栈和队列在实际应用中的重要性和有效性。
2.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如中缀表达式转后缀表达式的算法设计、表达式求值的优化等。
通过查阅资料和与同学的讨论,我们解决了这些问题,并完善了算法的实现。
3. 实验三:串的模式匹配3.1 实验目的本实验旨在掌握串的基本操作和模式匹配算法,并进行实际编程实现。
带头节点的循环单链表

带头节点的循环单链表带头节点的循环单链表是一种特殊的链表结构,它在普通的循环单链表的基础上增加了一个头节点。
本文将详细介绍带头节点的循环单链表的特点、操作以及应用场景。
一、带头节点的循环单链表的特点带头节点的循环单链表与普通的循环单链表相比,多了一个头节点,头节点不存储任何数据,仅作为链表的标志和辅助作用。
头节点的存在使得链表的插入、删除等操作更加方便,同时也能避免一些特殊情况的处理。
1. 初始化链表:创建一个头节点,并将头节点的指针指向自身,表示链表为空。
2. 判断链表是否为空:通过判断头节点的指针是否指向自身,即可判断链表是否为空。
3. 插入节点:在链表的指定位置插入一个新节点。
首先找到插入位置的前一个节点,然后将新节点的指针指向前一个节点的下一个节点,再将前一个节点的指针指向新节点。
4. 删除节点:删除链表中指定位置的节点。
首先找到要删除节点的前一个节点,然后将前一个节点的指针指向要删除节点的下一个节点,最后释放被删除节点的内存空间。
5. 遍历链表:从头节点开始,按照指针的方向遍历链表,直到回到头节点为止,输出每个节点的数据。
三、带头节点的循环单链表的应用场景带头节点的循环单链表在实际应用中有着广泛的应用场景,以下是几个典型的应用场景:1. 约瑟夫环问题:约瑟夫环是一种数学问题,通过使用带头节点的循环单链表可以很方便地解决该问题。
2. 循环队列:循环队列是一种常见的队列结构,使用带头节点的循环单链表可以实现循环队列的操作。
3. 循环链表:带头节点的循环单链表本身就是一种循环链表,可以用于解决一些需要循环访问的问题。
总结:带头节点的循环单链表是一种特殊的链表结构,通过增加一个头节点,使得链表的操作更加方便,并且能够避免一些特殊情况的处理。
带头节点的循环单链表可以用于解决一些需要循环访问的问题,例如约瑟夫环问题和循环队列等。
掌握带头节点的循环单链表的基本操作,对于理解和应用链表结构具有重要的意义。
带头结点的单链表的插入算法

带头结点的单链表的插入算法在计算机科学中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
链表有多种形式,其中一种是带头结点的单链表。
带头结点的单链表是在普通的单链表的基础上添加了一个头结点,头结点不存储数据,只用来标识链表的开始。
带头结点的单链表的插入算法是指在链表中插入新的节点的操作。
下面将详细介绍带头结点的单链表的插入算法。
带头结点的单链表的插入算法包括以下几个步骤:1. 首先,创建一个新的节点,该节点包含要插入的数据。
2. 然后,找到插入位置的前一个节点,可以从头结点开始遍历链表,直到找到插入位置的前一个节点为止。
3. 接下来,将新节点的指针指向插入位置的后一个节点。
4. 最后,将插入位置的前一个节点的指针指向新节点。
下面通过一个具体的例子来说明带头结点的单链表的插入算法。
假设有一个带头结点的单链表,初始状态下只有一个头结点。
现在要在链表中插入一个新节点,该节点的数据为10。
1. 首先,创建一个新的节点,节点的数据为10。
2. 然后,从头结点开始遍历链表,直到找到插入位置的前一个节点。
在这个例子中,由于链表只有一个头结点,所以插入位置的前一个节点就是头结点。
3. 接下来,将新节点的指针指向插入位置的后一个节点。
由于链表只有一个头结点,所以插入位置的后一个节点为空。
4. 最后,将插入位置的前一个节点的指针指向新节点。
在这个例子中,将头结点的指针指向新节点。
经过以上操作,新节点就成功地插入到了链表中。
带头结点的单链表的插入算法的时间复杂度为O(n),其中n为链表的长度。
这是因为在最坏情况下,需要遍历整个链表找到插入位置的前一个节点。
带头结点的单链表的插入算法在实际应用中有着广泛的应用。
例如,在图算法中,可以使用带头结点的单链表来表示图的邻接表。
插入节点的操作可以用来添加新的边或顶点。
带头结点的单链表的插入算法是一种常见的数据操作,它可以在链表中插入新的节点。
数据结构实验报告单链表

数据结构实验报告_单链表数据结构实验报告——单链表一、实验目的1.掌握单链表的基本概念和原理。
2.了解单链表在计算机科学中的应用。
3.掌握单链表的基本操作,如插入、删除、遍历等。
4.通过实验,加深对理论知识的理解,提高编程能力。
二、实验内容1.实验原理:单链表是一种线性数据结构,由一系列节点组成,每个节点包含数据域和指针域。
其中,指针域指向下一个节点,最后一个节点的指针域指向空。
单链表的主要操作包括插入、删除、遍历等。
2.实验步骤:(1)创建一个单链表。
(2)实现插入操作,即在链表的末尾插入一个新节点。
(3)实现删除操作,即删除链表中的一个指定节点。
(4)实现遍历操作,即输出链表中所有节点的数据。
3.实验代码:下面是使用Python语言实现的单链表及其基本操作的示例代码。
class Node:def __init__(self, data):self.data = dataself.next = Noneclass LinkedList:def __init__(self):self.head = Nonedef insert(self, data):new_node = Node(data)if self.head is None:self.head = new_nodeelse:current = self.headwhile current.next is not None:current = current.nextcurrent.next = new_nodedef delete(self, data):if self.head is None:returnif self.head.data == data:self.head = self.head.nextreturncurrent = self.headwhile current.next is not None and current.next.data != data:current = current.nextif current.next is None:returncurrent.next = current.next.nextdef traverse(self):current = self.headwhile current is not None:print(current.data)current = current.next4.实验结果:通过运行上述代码,我们可以看到单链表的基本操作得到了实现。
北京邮电大学 计算机学院 数据结构第一次实验报告

printf("Delete failed!\n");
printlist(L,L->head);
return 0;
}
else
{
S=get(L,L->head,min,0);//0和1为开关,进行设置
R=get(L,S,max,1);
if(min>=L->head->data)//判断删除的节点中是否包含头结点
while(S!=NULL)
{
printf("%d--->",S->data);
S=S->next;
}
printf("NULL\n");
}
}
void deletelist(Linklist R)//释放链表
{
Linklist temp;
while(R!=NULL)
{
temp=R;
R=R->next;
scanf("%d",&L->len);
fflush(stdin);
if(L->len<=0)
return 0;
printf("Please input the data:\n");
for(i=0;i<=L->len-1;i++)
{
S=(Linklist)malloc(sizeof(Lnode));
要求:请同学把步骤、调试好的程序及存在的问题写在下面。
第一题实验程序代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct Lnode{
数据结构实验报告-实验一顺序表、单链表基本操作的实现

数据结构实验报告-实验⼀顺序表、单链表基本操作的实现实验⼀顺序表、单链表基本操作的实现l 实验⽬的1、顺序表(1)掌握线性表的基本运算。
(2)掌握顺序存储的概念,学会对顺序存储数据结构进⾏操作。
(3)加深对顺序存储数据结构的理解,逐步培养解决实际问题的编程能⼒。
l 实验内容1、顺序表1、编写线性表基本操作函数:(1)InitList(LIST *L,int ms)初始化线性表;(2)InsertList(LIST *L,int item,int rc)向线性表的指定位置插⼊元素;(3)DeleteList1(LIST *L,int item)删除指定元素值的线性表记录;(4)DeleteList2(LIST *L,int rc)删除指定位置的线性表记录;(5)FindList(LIST *L,int item)查找线性表的元素;(6)OutputList(LIST *L)输出线性表元素;2、调⽤上述函数实现下列操作:(1)初始化线性表;(2)调⽤插⼊函数建⽴⼀个线性表;(3)在线性表中寻找指定的元素;(4)在线性表中删除指定值的元素;(5)在线性表中删除指定位置的元素;(6)遍历并输出线性表;l 实验结果1、顺序表(1)流程图(2)程序运⾏主要结果截图(3)程序源代码#include<stdio.h>#include<stdlib.h>#include<malloc.h>struct LinearList/*定义线性表结构*/{int *list; /*存线性表元素*/int size; /*存线性表长度*/int Maxsize; /*存list数组元素的个数*/};typedef struct LinearList LIST;void InitList(LIST *L,int ms)/*初始化线性表*/{if((L->list=(int*)malloc(ms*sizeof(int)))==NULL){printf("内存申请错误");exit(1);}L->size=0;L->Maxsize=ms;}int InsertList(LIST *L,int item,int rc)/*item记录值;rc插⼊位置*/ {int i;if(L->size==L->Maxsize)/*线性表已满*/return -1;if(rc<0)rc=0;if(rc>L->size)rc=L->size;for(i=L->size-1;i>=rc;i--)/*将线性表元素后移*/L->list[i+=1]=L->list[i];L->list[rc]=item;L->size++;return0;}void OutputList(LIST *L)/*输出线性表元素*/{int i;printf("%d",L->list[i]);printf("\n");}int FindList(LIST *L,int item)/*查找线性元素,返回值>=0为元素的位置,返回-1为没找到*/ {int i;for(i=0;i<L->size;i++)if(item==L->list[i])return i;return -1;}int DeleteList1(LIST *L,int item)/*删除指定元素值得线性表记录,返回值为>=0为删除成功*/ {int i,n;for(i=0;i<L->size;i++)if(item==L->list[i])break;if(i<L->size){for(n=i;n<L->size-1;n++)L->list[n]=L->list[n+1];L->size--;return i;}return -1;}int DeleteList2(LIST *L,int rc)/*删除指定位置的线性表记录*/{int i,n;if(rc<0||rc>=L->size)return -1;for(n=rc;n<L->size-1;n++)L->list[n]=L->list[n+1];L->size--;return0;}int main(){LIST LL;int i,r;printf("list addr=%p\tsize=%d\tMaxsize=%d\n",LL.list,LL.size,LL.Maxsize);printf("list addr=%p\tsize=%d\tMaxsize=%d\n",LL.list,LL.list,LL.Maxsize);while(1){printf("请输⼊元素值,输⼊0结束插⼊操作:");fflush(stdin);/*清空标准输⼊缓冲区*/scanf("%d",&i);if(i==0)break;printf("请输⼊插⼊位置:");scanf("%d",&r);InsertList(&LL,i,r-1);printf("线性表为:");OutputList(&LL);}while(1){printf("请输⼊查找元素值,输⼊0结束查找操作:");fflush(stdin);/*清空标准输⼊缓冲区*/scanf("%d ",&i);if(i==0)break;r=FindList(&LL,i);if(r<0)printf("没有找到\n");elseprintf("有符合条件的元素,位置为:%d\n",r+1);}while(1){printf("请输⼊删除元素值,输⼊0结束查找操作:");fflush(stdin);/*清楚标准缓存区*/scanf("%d",&i);if(i==0)break;r=DeleteList1(&LL,i);if(i<0)printf("没有找到\n");else{printf("有符合条件的元素,位置为:%d\n线性表为:",r+1);OutputList(&LL);}while(1){printf("请输⼊删除元素位置,输⼊0结束查找操作:");fflush(stdin);/*清楚标准输⼊缓冲区*/scanf("%d",&r);if(r==0)break;i=DeleteList2(&LL,r-1);if(i<0)printf("位置越界\n");else{printf("线性表为:");OutputList(&LL);}}}链表基本操作l 实验⽬的2、链表(1)掌握链表的概念,学会对链表进⾏操作。
含头结点的单链表

实习报告——“含头结点的单链表”演示程序(一)、程序的功能和特点主要实现的功能有:1.查找给定关键字的结点;2.在单链表第L 个结点位置插入一个新结点;3.删除第L 个结点;4.显示全部链表;5.求链表的长度;(二)、程序的算法设计“比较”算法:1.【逻辑结构与存储结构设计】逻辑结构:每个元素之间是相邻的;存储结构:元素存储于任意的存储单元中,可以是连续的,也可以是不 连续的;2.【基本操作设计】元素存储域任意的存储单元中,这时需要在存储元素本身信息的同时,还要存储下一个元素的位置。
由此构成一个链状结构,成为链表。
将表示数据元素和下一个元素位置的结构,如下所示:称为链表的结点指针域用来存放下一个元素的地址,这样就可以保证表的连续性3.【算法设计】查找给定关键字的结点在单链表第L 个结点位置插入一个新结点数据元素 指针域 指向第一个结点不是当前所查找的结点并且没有到链尾 是移动指针,使其指向下一个元素 否 指针域!=null 否 是 null 返回结点 第L 个结点,新结点id删除第L个结点建立新结点指针P后移L个结点把P之后链表接到新结点的后面把新结点接在p所指结点的后面判断链表是否为空否是使指针p指向所要删结点的前驱null指向要删结点指向要删结点的后驱4.【高级语言代码】查找给定关键字的结点,返回结点LinkNodeNode p=first; //指向第一结点//不是当前结点并且没有到链尾while(p.iData!=id&&p.next!=null)p=p.next;if(p.next!=null) return p;else return null;在单链表第L个结点位置插入一个新结点LinkNodeNode newLinkNodeNode= new LinkNodeNode(id,fd); //诞生新结点newLinkNodeNodeint i=1;LinkNodeNode p=first; //指向第一结点//p指针后移L个结点while(p.next!=null && i++<L) p=p.next;newLinkNodeNode.next=p.next; //把p之后的链表接在新结点的后面p.next=newLinkNodeNode; //把新结点接在p所指结点的后面return true;删除第L个结点if(isEmpty()) return null;LinkNodeNode p=first; //指向第一个结点int i=1;while(p.next!=null && i++<L)p=p.next; //指向要删结点的前驱LinkNodeNode q=p.next; //指向要删结点p.next=q.next; //p指向要删结点的后继return q; //返回已删结点(三)、程序中类的设计“LinkNodeList”类:1.【逻辑结构与存储结构】逻辑结构:每个元素之间是相邻的;存储结构:元素存储于任意的存储单元中,可以是连续的,也可以是不连续的;2.【主要成员变量说明】public LinkNode first; //单链表的头指针【主要成员方法说明】查找给定关键字的结点,返回结点public LinkNode LinkNodeFind(int id)在单链表第L个结点位置插入一个新结点public boolean insertWhere(int L,int id)删除第L个结点public LinkNode deleteWhere(int L)显示全部链表public void listDisplay()返回链表长度(结点数)public int listLength()4.【高级语言代码】链表的结点类class LinkNode{public int iData; //数据域(结点关键字)public LinkNode next; //指针域(指向下一结点)public LinkNode() { //头结点构造方法iData=-1;//数据域赋值//指针域自动初始化为null}public LinkNode(int iD) { //结点构造方法iData=iD; //数据域赋值}public void LinkNodeDisplay(){ //显示自身的数据域System.out.println("["+iData+"]");}}单链表类class LinkNodeList {public LinkNode first; //单链表的头指针public LinkNodeList (){ //构造方法first=new LinkNode(); //空单链表,头指针指向头结点}public boolean isEmpty() { //单链表是否为空return (first.next==null); //头结点的指针为空}//查找给定关键字的结点,返回结点public LinkNode LinkNodeFind(int id) {LinkNode p=first; //指向第一结点//不是当前结点并且没有到链尾while(p.iData!=id&&p.next!=null)p=p.next;if(p.next!=null)return p;elsereturn null;}//在单链表第L个结点位置插入一个新结点public boolean insertWhere(int L,int id) {LinkNode newLinkNode= new LinkNode(id); //诞生新结点newLinkNodeint i=1;LinkNode p=first; //指向第一结点//p指针后移L个结点while(p.next!=null && i++<L) p=p.next;newLinkNode.next=p.next; //把p之后的链表接在新结点的后面p.next=newLinkNode; //把新结点接在p所指结点的后面return true;}//删除第L个结点public LinkNode deleteWhere(int L) {if(isEmpty()) return null;LinkNode p=first; //指向第一个结点int i=1;while(p.next!=null && i++<L)p=p.next; //指向要删结点的前驱LinkNode q=p.next; //指向要删结点p.next=q.next; //p指向要删结点的后继return q; //返回已删结点}//显示全部链表public void listDisplay() {LinkNode p=first.next; //指向第一个结点System.out.println("显示链表:从前到后");while(p!=null) {p.LinkNodeDisplay(); //显示结点p=p.next;}System.out.println("*******");}//返回链表长度(结点数)public int listLength() {LinkNode p=first.next; //指向头结点int i=0;while(p!=null){p=p.next;i++;}return i;}//置链表为空表public void makeEmpty() {first.next=null;}public static void main(String []args) {LinkNodeList s1=new LinkNodeList(); //空链表诞生s1.insertWhere(1,12); //从指定位置插入结点s1.insertWhere(2,34);s1.insertWhere(3,53);s1.insertWhere(4,32);s1.insertWhere(3,76);s1.listDisplay();s1.deleteWhere(4); //删除第4个结点s1.listDisplay();LinkNode t=s1.LinkNodeFind(34); //查找结点if(t!=null) t.LinkNodeDisplay(); //显示该结点//s1.makeEmpty();//s1.listDisplay();System.out.println(s1.listLength());}}(四)、程序的输入输出和运行结果截屏。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验报告实验名称:实验1——单链表的构造学生姓名:XXXXNB班级:XXXX班内序号:学号:XXXX日期:XXXXX1.实验要求根据线性表的抽象数据类型的定义,完成带头结点的单链表的基本功能。
单链表的基本功能:1、构造:使用头插法、尾插法两种方法2、插入:要求建立的链表按照关键字从小到大有序3、删除4、查找5、获取链表长度6、销毁7、其他:可自行定义编写测试main()函数测试线性表的正确性。
2.程序分编程完成单链表的一般性功能如单链表的构造:使用头插法、尾插法两种方法插入:要求建立的链表按照关键字从小到大有序,删除,查找,获取链表长度,销毁用《数据结构》中的相关思想结合C++语言基本知识编写一个单链表结构。
本程序为使用方便,几乎不用特殊的命令,只需按提示输入即可,适合更多的用户使用。
2.1 存储结构单链表的存储结构:2.2 关键算法分析1.头插法自然语言描述:a.在堆中建立新结点b.将a[i]写入到新结点的数据域c.修改新结点的指针域d.修改头结点的指针域,将新结点加入链表中//在构建之初为了链表的美观性构造,进行了排序代码描述://头插法构造函数template<class T>LinkList<T>::LinkList(T a[], int n){for (int i = n - 1; i >= 1; i--)//冒泡排序,对数组进行从小到大排序{for (int j = 0; j < i; j++){if (a[j]>a[j + 1]){T t = a[j + 1];a[j + 1] = a[j];a[j] = t;}}}front = new Node < T >;//为头指针申请堆空间front->next = NULL;//构造空单链表for (int i = n - 1; i >= 0; i--){Node<T>*s = new Node < T >;//建立新结点s->data = a[i];//将a[i]写入新结点的数据域s->next = front->next;//修改新结点的指针域front->next = s;//修改头结点的指针域,将新结点加入到链表中}}2.尾插法自然语言描述:a.在堆中建立新结点b.将a[i]写入到新结点的数据域c.将新结点加入到链表中d.修改修改尾指针代码描述://尾插法构造函数template<class T>LinkList<T>::LinkList(T a[], int n){front = new Node < T > ;Node<T>*r = front;//命名一个新变量进行转换for (int i = 0; i < n; i++){Node<T>*s = new Node < T > ;s->data = a[i];r->next = s;r = s;}r->next = NULL;}时间复杂度:O(n)3.析构函数自然语言描述:a.新建立一个指针,指向头结点b.移动a中建立的指针c.逐个释放指针代码描述:template<class T>LinkList<T>::~LinkList()//析构函数,销毁链表{Node<T> * p = front;while(p){front = p;p = p->next;delete front;}}4.按位查找函数自然语言描述: a.初始化工作指针p和计数器j,p指向第一个结点,j=1b.循环以下操作,直到p为空或者j等于1b1:p指向下一个结点b2:j加1c.若p为空,说明第i个元素不存在,抛出异常d.否则,说明p指向的元素就是所查找的元素,返回元素地址代码描述:template<class T>Node<T>* LinkList<T>::Get(int i)//按位查找{Node<T> * p = front;int j=0;while(p){if(j<i){p = p->next;j++;}else break;}if(!p) throw"查找位置非法";else return p;}时间复杂度:O(n)5.按值查找函数自然语言描述:a.初始化工作指针p和计数器j,p指向第一个结点,j=1b.循环以下操作,找到这个元素或者p指向最后一个结点b1.判断p指向的结点是不是要查找的值,如果是,返回j;b2.否则p指向下一个结点,并且j的值加一c.如果找到最后一个结点还没有找到要查找的元素,返回查找失败信息代码描述:template<class T>int LinkList<T>::Locate(T x)//按值查找{Node<T> * p = front->next;int j = 1;while(p){if(p->data == x) return j;else{p = p->next;j++;}}return -1;}时间复杂度:O(n)6.插入函数自然语言描述:a.在堆中建立新结点b.将要插入的结点的数据写入到新结点的数据域c.修改新结点的指针域d.修改前一个指针的指针域,使其指向新插入的结点的位置代码描述:template<class T>void LinkList<T>::Insert(int i,T x)//插入函数{Node<T> * p = Get(i-1);if(p){Node<T> * s = new Node<T>;s->data = x;s->next = p->next;p->next = s;}else throw"插入位置非法";}时间复杂度:O(n)7.按位删除函数自然语言描述:a.从第一个结点开始,查找要删除的位数i前一个位置i-1的结点b.设q指向第i个元素c.将q元素从链表中删除d.保存q元素的数据e.释放q元素代码描述:template<class T>T LinkList<T>::Delete(int i)//删除函数{Node<T> *p = Get(i-1);Node<T> *q = p->next;T x=q->data;p->next = q->next;delete q;return x;}8.遍历打印函数自然语言描述: a.判断该链表是否为空链表,如果是,报错b.如果不是空链表,新建立一个temp指针c.将temp指针指向头结点d.打印temp指针的data域e.逐个往后移动temp指针,直到temp指针的指向的指针的next域为空代码描述:template<class T>void LinkList<T>::PrintList()//打印链表{Node<T> * p = front->next;while(p){cout<<p->data<<' ';p = p->next;}cout<<endl;}9.获取链表长度函数自然语言描述:a.判断该链表是否为空链表,如果是,输出长度0b.如果不是空链表,新建立一个temp指针,初始化整形数n为0c.将temp指针指向头结点d.判断temp指针指向的结点的next域是否为空,如果不是,n加一,否则return ne.使temp指针逐个后移,重复d操作,直到temp指针指向的结点的next 域为0,返回n代码描述:template<class T>int LinkList<T>::GetLength()//分析链表长度{Node<T> * p = front;int i=0;while(p){p = p->next;i++;}return i-1;}2.3 其他异常处理采用try catch 函数处理异常如在插入时的异常处理:template<class T>void LinkList<T>::Insert(int i, T x){Node<T>*p = front;if (i != 1) p = Get(i - 1);try{if (p){Node<T>*s = new Node < T > ;s->data = x;s->next = p->next;p->next = s;}else throw i;}catch (int i){cout << "插入到位置 " << i << " 处" << "为错误位置"<<endl;}}3. 程序运行结果主函数流程图:测试截图:初始化链表,菜单创建执行功能:4. 总结.调试时出现了一些问题如:异常抛出的处理,书中并未很好的提及异常处理,通过查阅资料,选择用try catch 函数对解决。
2.心得体会了解了单链表的基本的操作函数实现,对链式存储结构有了较好的认识3.下一步的改进可以增加完善报错机制,增强程序的健壮性完整源代码://单链表的构造#include<iostream>using namespace std;template<class T>struct Node{T data;//数据域struct Node<T>*next;//指针域};template <class T>class LinkList{public:LinkList(){ front = new Node <T>; front->next = NULL; }//无参构造函数LinkList(T a[], int n);//有参构造函数,使用含有n个元素的数组a初始化单链表~LinkList(); //析构函数,(其在void main 函数最后一句语句之后自动执行,旨在释放栈空间)void PrintList(); //按次序遍历线性表中的各个数据元素int GetLength(); //获取线性表的长度Node <T> * Get(int i); //获取线性表第i个位置上的元素结点地址int Locate(T x); //查找线性表中值为x的元素,找到后返回其位置void Insert(int i, T x);//后插,在线性表的第i个位置上插入值为x的新元素void insert(int i, T x);//前插,在线性表的第i个位置上插入值为x的新元素T Delete(int i); //删除线性表第i个元素,并将该元素返回private:Node <T> * front; //头指针};//头插法构造函数template<class T>LinkList<T>::LinkList(T a[], int n){for (int i = n - 1; i >= 1; i--)//冒泡排序,对数组进行从小到大排序{for (int j = 0; j < i; j++){if (a[j]>a[j + 1]){T t = a[j + 1];a[j + 1] = a[j];a[j] = t;}}}front = new Node < T >;//为头指针申请堆空间front->next = NULL;//构造空单链表for (int i = n - 1; i >= 0; i--){Node<T>*s = new Node < T >;//建立新结点s->data = a[i];//将a[i]写入新结点的数据域s->next = front->next;//修改新结点的指针域front->next = s;//修改头结点的指针域,将新结点加入到链表中}}//尾插法构造函数//template<class T>//LinkList<T>::LinkList(T a[], int n)//{// front = new Node < T > ;// Node<T>*r = front;//命名一个新变量进行转换// for (int i = 0; i < n; i++)// {//Node<T>*s = new Node < T > ;//s->data = a[i];//r->next = s;//r = s;//}//r->next = NULL;//}template<class T>void LinkList<T>::PrintList()//遍历线性表元素并打印到屏幕{Node<T>*p = front->next;while (p){cout << p->data << " ";p = p->next;}cout << endl;}template<class T>LinkList<T>::~LinkList()//析构函数{Node<T>*p = front;//初始化工作指针Pwhile (p)//要释放的结点存在{front = p;p = p->next;delete front;//释放结点}}template<class T>Node <T> * LinkList<T>::Get(int i)//获取线性表第i个位置上的元素结点地址{Node<T>*p = front->next;int k = 1;while (p && (k != i)){p = p->next;k++;}return p;}template<class T>int LinkList<T>::Locate(T x)//按值查找某元素的位置{Node<T>*p = front->next;int k = 1;while (p&&(p->data != x)){p = p->next;k++;}return k;}//后插template<class T>void LinkList<T>::Insert(int i, T x){Node<T>*p = front;if (i != 1) p = Get(i - 1);try{if (p){Node<T>*s = new Node < T > ;s->data = x;s->next = p->next;p->next = s;}else throw i;}catch (int i){cout << "插入到位置 " << i << " 处" << "为错误位置"<<endl;}}template<class T>T LinkList<T>::Delete(int i){Node<T>*p = front;if (i != 1) p = Get(i - 1);//若不是在第一个位置删除,获取第i-1个元素的地址try{if (p && (p->next)){Node<T>*q = p->next;p->next = q->next;T x = q->data;delete q;return x;}else throw i;}catch (int i){cout << "删除位置 " << i << " 处" << "为错误位置" << endl;}}template<class T>int LinkList<T>::GetLength(){Node<T>*p = front->next;int i;for (i = 0; p != NULL; i++){p = p->next;}return i;}void main(){int m=1;int a[7] = { 3, 2, 1, 4, 6, 5, 7 };LinkList<int> list(a, 7);cout << "排序后的链表为:";list.PrintList();cout << "\t\t**************************************************" << endl << "\t\t※※" << endl<< "\t\t※对该单链表的操作※" << endl<< "\t\t※※" << endl<< "\t\t※ 1. 获取线性表的长度※" << endl<< "\t\t※※" << endl<< "\t\t※ 2. 查找值为x的元素,并返回其位置※" << endl<< "\t\t※※" << endl<< "\t\t※ 3. 在线性表的第i个位置上插入值为x的新元素※" << endl<< "\t\t※※" << endl<< "\t\t※ 4. 删除线性表第i个元素,并将该元素返回※" << endl<< "\t\t※※" << endl<< "\t\t**************************************************" << endl << endl;while (m != 0){cout<< "\t\t\t选择你需要的功能:";int choice;cin >> choice;//输入需要的功能switch (choice){case 1:cout << "线性表的长度为:" << list.GetLength()<<endl;//获取线性表的长度break;case 2://查找值为x的元素,并返回其位置{cout << "请输入想查找的元素的值:" << endl;int value;cin >> value;int location = list.Locate(value);cout << "该元素的位置为:" << location << endl;}break;case 3://在线性表的第i个位置上插入值为x的新元素{cout << "请输入想插入的位置值:" << endl;int location_2;//位置值cin >> location_2;cout << "请输入想插入的新元素的值" << endl;int value_1;//元素值cin >> value_1;list.Insert(location_2, value_1);cout << "执行插入操作后的链表为:" << endl;list.PrintList();}break;case 4:// 删除线性表第i个元素,并将该元素返回{cout << "请输入想要删除的元素的位置值:" << endl;int location_3;cin >> location_3;int value_2 = list.Delete(location_3);cout << "删除的元素值为:" << value_2 << endl;}break;default:cout << "!!无此功能项" << endl;break;}cout << " ※※※那您是否想继续?继续请输入 1 不想继续请输入 0 ※※※" << endl;cin >> m;}}。