单链表的插入和删除实验报告Word文件下载.docx
《单链表的插入和删除实验报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《单链表的插入和删除实验报告Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
r->
next=NULL;
Input#toend"
//输入“#”代表输入结束
PleaseinputNode_data:
//输入各结点的字符串while(strcmp(ch,"
#"
)!
=0){
pp=LocateNode(head,ch);
//按值查找结点,返回结点指针
if(pp==NULL){//没有重复的字符串,插入到链表中
s=(ListNode*)malloc(sizeof(ListNode));
strcpy(s->
data,ch);
next=s;
r=s;
returnhead;
//返回头指针
//==========按值查找结点,找到则返回该结点的位置,否则返
回NULL==========
ListNode*LocateNode(LinkListhead,char*key)
ListNode*p=head->
next;
//从开始结点比较
while(p&
&
strcmp(p->
data,key)!
=0)//直到p为NULL或
p->
data为key止
p=p->
//扫描下一个结点
returnp;
//若p=NULL则查找失败,否则p指向找到的值
key的结点
//==========删除带头结点的单链表中的指定结点=======voidDeleteList(LinkListhead,char*key)
ListNode*p,*r,*q=head;
p=LocateNode(head,key);
//按key值查找结点的if(p==NULL){//若没有找到结点,退出printf("
positionerror"
exit(0);
while(q->
next!
=p)//p为要删除的结点,q为p的前结点q=q->
r=q->
q->
next=r->
free(r);
//释放结点
//===========打印链表=======voidprintlist(LinkListhead)
//从开始结点打印while(p){
%s,"
p->
data);
\n"
voidDeleteAll(LinkListhead)
ListNode*p=head,*r;
while(p->
next){r=p->
free(p);
p=r;
free(p);
运行结果:
//theinsertfunction
加的添加结点的代码:
intInsert(ListNode*head)
ListNode*in,*p,*q;
intwh;
inputtheinsertnode:
in=(ListNode*)malloc(sizeof(ListNode));
in->
p=(ListNode*)malloc(sizeof(ListNode));
q=(ListNode*)malloc(sizeof(ListNode));
if(!
in)
return0;
in->
you
inputtheplacewhereyouwanttoinsert
data:
%d"
&
wh);
for(p=head;
wh>
0;
next,wh--);
q=p->
next=in;
next=q;
return1;
最后提示为OK添加成功
实验心得:
这个实验中主要修改的是ch和num把它们由指针改成数组因为不改的话在后面delect函数中会出现没有地址的情况找不到地址就不能执行功能然后把locate函数的判断语句改一下避免矛盾的出现。
实验二、二叉树操作
目的
掌握二叉树的定义、性质及存储方式,各种遍历算法
二、要求
采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序
和后序以及按层次遍历的操作,求所有叶子及结点总数的操作。
三、程序源代码
#include"
stdio.h"
string.h"
#defineMax20//结点的最大个数
typedefstructnode{
chardata;
structnode*lchild,*rchild;
}BinTNode;
//自定义二叉树的结点类型
typedefBinTNode*BinTree;
//定义二叉树的指针
//==========基于先序遍历算法创建二叉树==============//=====要求输入先序序列,其中加入虚结点“#”以示空指针的位
BinTreeCreatBinTree(void)
BinTreeT;
charch;
if((ch=getchar())=='
#'
)
return(NULL);
//读入#,返回空指针
else{
T=(BinTNode*)malloc(sizeof(BinTNode));
//生成结点
T->
data=ch;
lchild=CreatBinTree();
//构造左子树
rchild=CreatBinTree();
//构造右子树
return(T);
//========NLR先序遍历=============
voidPreorder(BinTreeT)
if(T){
Preorder(T->
lchild);
rchild);
//先序遍历左子树
//先序遍历右子树
//========LNR中序遍历===============
voidInorder(BinTreeT)
//中序遍历左子树
//访问结点
//中序遍历右子树
Inorder(T->
printf("
%c"
T->
Inorder(T->
//==========LRN后序遍历============voidPostorder(BinTreeT)
//后序遍历左子树
//后序遍历右子树
Postorder(T->
//求左深度
//求右深度
//取左右深度的最大值
//求结点数
//若左右深度为0,即为叶子
//
采用后序遍历求二叉树的深度、结点数及叶子数的递归算
法========
intTreeDepth(BinTreeT)
inthl,hr,max;
if(T){
hl=TreeDepth(T->
hr=TreeDepth(T->
max=hl>
hr?
hl:
hr;
NodeNum=NodeNum+1;
if(hl==0&
hr==0)leaf=leaf+1;
return(max+1);
elsereturn(0);
//====利用“先进先出
voidLevelorder(BinTreeT)
intfront=0,rear=1;
BinTNode*cq[Max],*p;
//定义结点的指针数组cq
cq[1]=T;
//根入队
while(front!
=rear)
{front=(front+1)%NodeNum;
p=cq[front];
//出队printf("
//出队,输出结点的值if(p->
lchild!
=NULL){rear=(rear+1)%NodeNum;
cq[rear]=p->
lchild;
//左子树入队
if(p->
rchild!
rchild;
//右子树入队
//==========主函数=================
voidmain()
BinTreeroot;
inti,depth;
CreatBin_Tree;
Inputpreorder:
//输入完全二叉树
//用#代表虚结点,如
root=CreatBinTree();
//创建二叉树,返回根结点
do{
//从菜单中选择遍历方式,输入序号。
ABD###CE##F##
\t
select
\t1:
PreorderTraversal\n"
\t2:
IorderTraversal\n"
\t3:
Postordertraversal\n"
\t4:
PostTreeDepth,Nodenumber,Leafnumber\n"
\t5:
LevelDepth\n"
//按层次遍历之前,先选择4,求出该树的结点数。
\t0:
Exit\n"
\tscanf("
i);
//输入菜单序号(0-5)
switch(i){
case1:
PrintBin_treePreorder:
"
Preorder(root);
//先序遍历
break;
case2:
PrintBin_TreeInorder:
Inorder(root);
//中序遍历
case3:
PrintBin_TreePostorder:
Postorder(root);
//后序遍历
case4:
depth=TreeDepth(root);
//求树的深度及叶子数
BinTreeDepth=%dBinTreeNodenumber=%d"
depth,NodeNum);
BinTreeLeafnumber=%d"
leaf);
case5:
LevePrintBin_Tree:
Levelorder(root);
//按层次遍历
default:
exit
(1);
}while(i!
=0);
执行程序
1.先序遍历
2.中序遍历
3.后序遍历
4.结点数叶子数高度
5..层次遍历
自己设计的:
abdhl##m##i##e#jn###cf#ko###g##
1.预计先序遍历结果:
abdhlmiejncfkog
2.预计中序遍历结果:
lhmdibenjafokcg
3.预计后序遍历结果:
lmhidnjebokfgca
4.结点数15高度5叶子数6
实际结果:
实验心得:
这次实验主要是要让我们熟练树及其相关知识熟练掌握先序中序后序遍历,层次遍历然后我们自己画一个图会实现以上功能以及叶子数结点数还有高度的计算程序里面大量运用了递归以及队的应用,
实验三、图的遍历操作
一、目的
掌握有向图和无向图的概念;
掌握邻接矩阵和邻接链表建立图的存储结构;
掌握DFS及BFS对图的遍历操作;
了解图结构在人工智能、工程等领域的广泛应用。
采用邻接矩阵和邻接链表作为图的存储结构,完成有向图和无向图的DFS和BFS操作。
三、DFS和BFS的基本思想
深度优先搜索法DFS的基本思想:
从图G中某个顶点Vo出发,首先访问Vo,然后选择一个与Vo相邻且没被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且没被访问过的顶点Vj访问,⋯⋯依次继续。
如果当前被访问过的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样方法向前遍历。
直到图中所有的顶点都被访问。
广度优先算法BFS的基本思想:
从图G中某个顶点Vo出发,首先访问Vo,然后访问与Vo相邻的所有未被访问过的顶点V1,V2,⋯⋯,Vt;
再依次访问与V1,V2,⋯⋯,Vt相邻的起且未被访问过的的所有顶点。
如此继续,直到访问完图中的所有顶点。
四、程序源代码
1.邻接矩阵作为存储结构的程序示例#include"
#include"
stdlib.h"
#defineMaxVertexNum100//定义最大顶点数
typedefstruct{
charvexs[MaxVertexNum];
//顶点表
intedges[MaxVertexNum][MaxVertexNum];
//邻接矩阵,可看作边表
intn,e;
//图中的顶点数n和边数e
}MGraph;
//用邻接矩阵表示的图的类型
//=========建立邻接矩阵=======voidCreatMGraph(MGraph*G)
inti,j,k;
chara;
InputVertexNum(n)andEdgesNum(e):
%d,%d"
G->
n,&
e);
//输入顶点数和边数
a);
InputVertexstring:
for(i=0;
i<
n;
i++)
vexs[i]=a;
//读入顶点信息,建立顶点表
for(j=0;
j<
j++)
edges[i][j]=0;
//初始化邻接矩阵
Inputedges,CreatAdjacencyMatrix\n"
for(k=0;
k<
e;
k++){//读入e条边,建立邻接矩阵scanf("
%d%d"
i,&
j);
//输入边(Vi,Vj)的顶点序号
edges[i][j]=1;
edges[j][i]=1;
//若为无向图,矩阵为对称矩阵;
若建立有向图,去掉该条语句
typedefenum{FALSE,TRUE}Boolean;
Booleanvisited[MaxVertexNum];
//========DFS:
深度优先遍历的递归算法======voidDFSM(MGraph*G,inti)
{//以Vi为出发点对邻接矩阵表示的图G进行DFS搜索,邻接矩阵是0,1矩阵
//访问顶点Vi
//置已访问标志
//依次搜索Vi的邻接点
//(Vi,Vj)∈E,且Vj未访
intj;
G->
vexs[i]);
visited[i]=TRUE;
if(G->
edges[i][j]==1&
!
visited[j])
DFSM(G,j);
问过,故Vj为新出发点
voidDFS(MGraph*G)
inti;
//标志向量初始化
visited[i]=FALSE;
DFSM(G,i);
//以Vi为源点开始DFS搜索
inti,j,f=0,r=0;
intcq[MaxVertexNum];
for(i=0;
i++)visited[i]=FALSE;
cq[i]=-1;
vexs[k]);
visited[k]=TRUE;
cq[r]=k;
//Vk将其序号入队
while(cq[f]!
=-1){
i=cq[f];
f=f+1;
//===========BFS:
广度优先遍历=======
voidBFS(MGraph*G,intk)
{//以Vk为源点对用邻接矩阵表示的图G进行广度优先搜索
//定义队列
//队列初始化
//访问源点Vk
已访问,将其入队。
注意,实际上是
//队非空则执行
//Vf出队
//依次Vi的邻接点Vj
visited[j]){//Vj未访问
vexs[j]);
//访问Vjvisited[j]=TRUE;
r=r+1;
cq[r]=j;
//访问过Vj入队
//==========main=====
MGraph*G;
G=(MGraph*)malloc(sizeof(MGraph));
//为图G申请内存空间
CreatMGraph(G);
//建立邻接矩阵printf("
PrintGraphDFS:
DFS(G);
//深度优先遍历printf("
PrintGraphBFS:
BFS(G,3);
//以序号为3的顶点开始广度优先遍历
调试结果:
自己画的图:
1对应顶点下标0以此类推9对应下标8预计运行结果:
DFS:
012345678
BFS:
324105687
对应我这个图:
DFS:
123456789
BFS:
435216798
图在数据结构中是相当重要的一部分联系很多现实问题图的根本就是顶点和边通过顶点和边建立邻接矩阵以及邻接链表广度搜索和深度搜索是此算法着重关注的地方。
要学会自己画图然后写出这两种搜索的结果,程序中用了队的算法是亮点通过TRUE和FAUSE来标记顶点是否以及访问避免重复
实验四、排序
掌握各种排序方法的基本思想、排序过程、算法实现,能进行时间和空间性能的分析,根据实际问题的特点和要求选择合适的排序方法。
实现直接排序、冒泡、直接选择、快速、堆、归并排序算法。
比较各种算法的运行速度。
三、程序示例
#defineMax100//假设文件长度
typedefstruct{//定义记录类型
intkey;
//关键字项
}RecType;
typedefRecTypeSeqList[Max+1];
//SeqList
为顺序表,表中第0
个元素作为哨兵
intn;
//顺序表实际的长度
1、直接插入排序的基本思想:
每次将一个待排序的记录,按其关键字大小插入到前面已排序好的子文件中的适当位置,直到全部记录插入完成为止。
//==========直接插入排序法======
voidInsertSort(SeqListR)
{//对顺序表R中的记录R[1‥n]按递增序进行插入排序
inti,j;
if(R[i].key<
R[i-1].key){//若R[i].key大于等于有序区中所有的keys,则R[i]留在原位
R[0]=R[i];
j=i-1;
//R[0]是R[i]的副本
do{//从右向左在有序区R[1‥i-1]中查找R[i]的位置
R[j+1]=R[j];
//将关键字大于R[i].key的记录后移j--;
}while(R[0].key<
R[j].key);
//当R[