北邮数据结构实验 第一次实验 线性表.docx
《北邮数据结构实验 第一次实验 线性表.docx》由会员分享,可在线阅读,更多相关《北邮数据结构实验 第一次实验 线性表.docx(18页珍藏版)》请在冰豆网上搜索。
北邮数据结构实验第一次实验线性表
1.实验要求
(1)实验目的
通过选择下面题目进行实现,掌握如下内容:
Ø熟悉C++语言的基本编程方法,掌握集成编译环境的调试方法
Ø学习指针、模板类、异常处理的使用
Ø掌握线性表的操作的实现方法
Ø学习使用线性表解决实际问题的能力
(2)实验内容
根据线性表的抽象数据类型的定义,选择下面任一种链式结构实现线性表,并完成线性表的基本功能。
线性表存储结构(五选一):
1、带头结点的单链表
2、不带头结点的单链表
3、循环链表
4、双链表
5、静态链表
线性表的基本功能:
1、构造:
使用头插法、尾插法两种方法
2、插入:
要求建立的链表按照关键字从小到大有序
3、删除
4、查找:
按位置查找和按值查找
5、获取链表长度
6、销毁
7、其他:
可自行定义
编写测试main()函数测试线性表的正确性。
2.程序分析
2.1存储结构
储存结构:
单链表
a3
1080H
……
a1
10C0H
……
a4
^
……
a2
1000H
……
地址内存单元
结点
1000H
结点
头指针1020H
结点
1080H
10C0H
结点
2.2关键算法分析
一、关键算法:
1.头插法
自然语言描述:
a:
在堆中建立新结点
b:
将a[i]写入新结点的数据域
c:
修改新结点的指针域
d:
修改头结点的指针域。
将新结点加入链表中。
2.尾插法
伪代码描述:
a:
Node*s=newNode
b:
s->data=a[i];
c:
r->next=s;
d:
r=s;
3.析构/删除函数
a:
Node*p=front
b:
while(p)
c:
front=p
d:
p=p->next
e:
deletefront
4.按位查找函数
a:
Node*p=front->next;j=1;
b:
while(p&&j!
=1)
b1:
p=p->next;
b2:
j++:
c:
if(!
p)throw”end”
d:
returnp;
5.按值查找函数
a:
Node*p=front->next;j=1;
b:
while(p)
b1:
if(p->next==x)returnj
p=p->next;
j++
c:
return“error”
6.插入函数
a:
Node*s=newNode;
b:
s-data=p->data
c:
s->next=p->next;
d:
p->next=s
e:
p->data=x
7.删除函数
a:
q=p->next;
b:
p->next=q->next
c:
x=q->data
d:
deleteq
8.遍历打印函数
Iffront->next==NULL
Throw“anemptylist”
Node*temp=front->next;
While(temp->next)
{
cout<data<<”“;
temp=temp->next;
}
9.获取链表长度函数
Intn=0;
Iffront->next==NULL
n=0;
else
{
Node*temp=front->next;
While(temp->next)
n++;
temp=temp->next;
}
Returnn;
二、代码详细分析
1.删除算法:
图1删除结点示意图
算法步骤:
①从第一个结点开始,查找第i-1个元素,设为p指向该a结点;
②设q指向第i个元素:
q=p->next;
③摘链,即将q元素从链表中摘除:
p->next=q->next;
④保存q元素的数据:
x=q->data;
⑤释放q元素:
deleteq;
2.头插法
关键代码:
a:
在堆中建立新结点:
Node*s=newNode;
b:
将a[i]写入到新结点的数据域s->data=a[i];
c:
修改新结点的指针域s->next=front->next;
d:
修改头结点的指针域front->next=s;
front
s
front
3.尾插法
关键代码:
a:
在堆中建立新结点Node*s=newNode;
b:
将数据写入结点的数据域s->data=a[i];
c将新结点加入到链表中:
r->next=s;
d修改尾指针r=s;
r
Front
Front
S
4.查找算法
关键代码:
aNode*p=front->next;intj=1;
bwhile(p&&j!
=1)
{
p=p->next;
j++;
}
front
P(j=1)P(j=2)P(j=i)P(j=n)
三、计算关键算法的时间、空间复杂度
头插法/尾插法O(n);
按位/按值查找O(n);
插入操作O(n);
3.程序运行结果
运行结果:
流程图:
开始
初始化一个对象
初始化一个整数数组,作为赋值准备
分别利用头插法和尾插法初始化,并用遍历打印函数来显示数值
执行删除函数,之后用遍历打印函数测试是否真的删除
执行插入函数,之后用遍历打印函数测试是否真的插入
执行按位查找和按值查找
结束
问题规模的数量级为10,插入元素位置为第10个,删除第3个
4.总结
1.调试时出现的问题及解决方法:
按位查找时,返回值与计数器j的关系没有找对,导致返回值不在链表中,
解决:
重新计算两者关系。
2.心得体会
通过这次实验,我熟悉了链表的储存结构以及各种操作
3.改进:
适当简化某些过程,使程序更精简。
源文件:
#include
usingnamespacestd;
template
structNode
{
Tdata;
structNode*next;
};
template
classLinkList
{
public:
LinkList(){front=newNode;front->next=NULL;}
voidhLinkList(Ta[],intn);//头插法
voidrLinkList(Ta[],intn);//尾插法
~LinkList();//析构/删除
intGetLength();//获取长度
Node*Get(inti);
intLocate(Tx);
voidInsert(inti,Tx);
TDelete(inti);
voidPrintList();
private:
Node*front;
};
template
voidLinkList:
:
hLinkList(Ta[],intn)
{
front=newNode;
front->next=NULL;
for(inti=n-1;i>0;i--)
{
Node*s=newNode;
s->data=a[i];
s->next=front->next;
front->next=s;
}
};
template
voidLinkList:
:
rLinkList(Ta[],intn)
{
front=newNode;
Node*r=front;
for(inti=0;i<=n-1;i++)
{
Node*s=newNode;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
};
template
LinkList:
:
~LinkList()
{
Node*temp=front;
while(temp)
{
front=temp;
temp=temp->next;
deletefront;
}
};
template
Node*LinkList:
:
Get(inti)
{
Node*p=front->next;
intj=1;
while(p&&j!
=i)
{
p=p->next;
j++;
}
if(!
p)throw"查找位置非法";
elsereturnp;
};
template
intLinkList:
:
Locate(Tx)
{
Node*p=front->next;
intj=1;
while(p)
{
if(p->data==x)return4*j;
p=p->next;
j++;
};
return-1;//对查找位置异常的处理,返回-1
};
template
voidLinkList:
:
Insert(inti,Tx)
{
Node*p=front;
if(i!
=1)p=Get(i-1);
if(p)
{
Node*s=newNode;
s->data=x;
s->next=p->next;
p->next=s;
}
elsethrow"插入位置错误";
};
template
TLinkList:
:
Delete(inti)
{
Node*p=front;
if(i!
=1)p=Get(i-1);
Node*q=p->next;
p->next=q->next;
Tx=q->data;
deleteq;
returnx;
};
template
voidLinkList:
:
PrintList()//遍历打印链表元素
{
if(front->next==NULL)
cout<<"该链表为空链表"<Node*temp=front->next;
while(temp->next)
{
cout<data<<"";
temp=temp->next;
}
};
template
intLinkList:
:
GetLength()
{
intn=0;
if(front->next==NULL)
{
n=0;
}
else
{
Node*temp=front->next;
while(temp->next)
{
n++;
temp=temp->next;
}
}
returnn;
};
voidmain()
{
LinkListlinklist1;
intall[100];
for(inti=0;i<100;i++)
{
all[i]=2*i;
};
linklist1.hLinkList(all,50);
cout<<"利用遍历函数打印输出所有的数值:
"<linklist1.PrintList();
cout<intm=linklist1.GetLength();
cout<<"利用获取长度获取该链表的长度为:
"<cout<cout<<"利用查找函数查找20所在的地址为:
"<cout<<"利用按位查找函数查找第30个数据为:
"<cout<<"插入函数,插入后遍历打印结果为:
"<linklist1.Insert(10,3445);
linklist1.PrintList();
cout<cout<<"删除某一位后的结果为:
"<linklist1.Delete(3);
linklist1.PrintList();
}