单链表的插入和删除实验报告.docx
《单链表的插入和删除实验报告.docx》由会员分享,可在线阅读,更多相关《单链表的插入和删除实验报告.docx(27页珍藏版)》请在冰豆网上搜索。
单链表的插入和删除实验报告
实验一、单链表的插入和删除
一、目的
了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。
二、要求:
建立一个数据域定义为字符串的单链表,在链表中不允许有重复的字符串;根据输入的字符串,先找到相应的结点,后删除之。
voidDeleteList();//函数,删除指定值的结点
voidprintlist();//函数,打印链表中的所有值
voidDeleteAll();//函数,删除所有结点,释放内存
//==========主函数==============voidmain()
(
charch[10],num[10];
LinkListhead;
head=CreatListR1();//用尾插入法建立单链表,返回头指针
printlist(head);//遍历链表输出其值
printf("Deletenode(y/n):
");//输入“y”或“n”去选择是否
删除结点
scanf("%s",num);
if(strcmp(num,"y")==0||strcmp(num,"Y")==0){
printf("PleaseinputDelete_data:
");
scanf("%s”,ch);//输入要删除的字符串
DeleteList(head,ch);
printlist(head);
}
DeleteAll(head);//删除所有结点,释放内存
}
//==========用尾插入法建立带头结点的单链表===========
LinkListCreatListRI(void)(
charch[10];
LinkListhead=(LinkList)malloc(sizeof(ListNode));//生成
头结点
ListNode*s,*r,*pp;
r=head;
r->next=NULL;
printf("Input#toend");//输入“#”代表输入结束
printf("PleaseinputNode_data:
");
scanf("%s”,ch);//输入各结点的字符串
while(strcmp(ch,"#")!
=0)(
pp=LocateNode(head,ch);//按值查找结点,返回结点指针
if(pp==NULL)(//没有重复的字符串,插入到链表中
s=(ListNode*)malloc(sizeof(ListNode));
strcpy(s->data,ch);
r->next=s;
r=s;
r->next=NULL;
}
printf("Input#toend");
printf("PleaseinputNode_data:
");
scanf("%s",ch);
returnhead;//返回头指针
}
//==========按值查找结点,找到则返回该结点的位置,否则返回
NULL==========
ListNode*LocateNode(LinkListhead,char*key)
(
ListNode*p=head->next;//从开始结点比较
while(p&&strcmp(p->data,key)!
=0)//直到p为NUL或p->
data为key止
p=p->next;//扫描下一个结点
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->next;
r=q->next;
q->next=r->next;
free(r);//释放结点
}
//===========打印链表=======voidprintlist(LinkListhead)
(
ListNode*p=head->next;//从开始结点打印
while(p)(
printf("%s,",p->data);
p=p->next;
}
printf("\n");
}
//==========删除所有结点,释放空间===========
voidDeleteAll(LinkListhead)
ListNode*p=head,*r;
while(p->next)(
r=p->next;
free(p);
p=r;
}
free(p);
}
运行结果:
加的添加结点的代码:
intInsert(ListNode*head)//theinsertfunction
(
ListNode*in,*p,*q;
intwh;
in=(ListNode*)malloc(sizeof(ListNode));in->next=NULL;
p=(ListNode*)malloc(sizeof(ListNode));p->next=NULL;
q=(ListNode*)malloc(sizeof(ListNode));q->next=NULL;
if(!
in)
return0;
scanf("%s”,in->data);
printf("inputtheplacewhereyouwanttoinsertyoudata:
");
scanf("%d”,&wh);
for(p=head;wh>0;p=p->next,wh--);
q=p->next;
p->next=in;
in->next=q;
return1;
}
运行结果:
InputInput
InputInput
Inputdh.
ttttttttcha^
endendendendend
Please
Please
Please
Please
Please
inputinputinputinputinput
eefcrhfaej.
Deletenode(y/n):
ninsertor
not?
input
input
the
the
Node_data:
dhNode_data:
chaNode_data:
eeFcNode_data:
hfaeNode_data:
tt
insertnode:
CAde
placeuhereyouuanttoinsertyoudata:
2
keytocontinue
最后提不■为OK添加成功
实验心得:
这个实验中主要修改的是ch和num把它们由指针改成
数组因为不改的话在后面delect函数中会出现没有地址的情况找不到地址就不能执行功能然后把locate函数的判断语句改一下避免矛盾的出现。
实验二、二叉树操作
一、目的
掌握二叉树的定义、性质及存储方式,各种遍历算法。
二、要求
采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序
和后序以及按层次遍历的操作,求所有叶子及结点总数的操作。
三、程序源代码
#include"stdio.h”
#include"string.h”
#defineMax20//结点的最大个数
typedefstructnode{
chardata;
structnode*lchild,*rchild;
}BinTNode;//白定义二叉树的结点类型
typedefBinTNode*BinTree;//定义二叉树的指针
intNodeNum,leaf;//NodeNum为结点数,leaf为叶子数
//==========基于先序遍历算法创建二叉树==============
//=====要求输入先序序列,其中加入虚结点“#”以示空指针的位置
BinTreeCreatBinTree(void)
(
BinTreeT;
charch;
if((ch=getchar())=='#')
return(NULL);//读入#,返回空指针
else(
T=(BinTNode*)malloc(sizeof(BinTNode));//生成结点
T->data=ch;
T->lchild=CreatBinTree();
T->rchild=CreatBinTree();
return(T);
}
}
//========NLR先序遍历=====
voidPreorder(BinTreeT)
(
if(T)(
printf("%c",T->data);//
//构造左子树
//构造右子树
访问结点
先序遍历左子树
Preorder(T->lchild);//
}
//========LNR中序遍历===============
voidInorder(BinTreeT)
(
//中序遍历左子树
//访问结点
//中序遍历右子树
if(T)(
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);
}
}
//==========LRN后序遍历============
voidPostorder(BinTreeT)(
if(T)(
后序遍历左子树
后序遍历右子树
Postorder(T->lchild);//
Postorder(T->rchild);//
printf("%c",T->data);//访问结点
//=====采用后序遍历求二叉树的深度、结点数及叶子数的递归算法
intTreeDepth(BinTreeT)
inthl,hr,max;
return(max+1);
elsereturn(0);
voidLevelorder(BinTreeT)
intfront=0,rear=1;
while(front!
=rear)
front=(front+1)%NodeNum;
if(p->lchild!
=NULL)(
rear=(rear+1)%NodeNum;
cq[rear]=p->lchild;//左子树入队
}
if(p->rchild!
=NULL)(
rear=(rear+1)%NodeNum;
cq[rear]=p->rchild;//右子树入队
}
}
}
//==========主函数=================
voidmain()
(
BinTreeroot;
inti,depth;
printf("\n");
printf("CreatBin_Tree;Inputpreorder:
");//输入完全二义
树的先序序列,
//用#代表虚结点,如
ABD###CE##F##
root=CreatBinTree();//创建二叉树,返回根结点
从菜单中选择遍历方式,输入序号。
printf("\t**********select************\n");
printf("\t1:
PreorderTraversal\n");
printf("\t2:
IorderTraversal\n");
printf("\t3:
Postordertraversal\n");
number\n");
4,求出该树的结点数。
printf("\t0:
Exit\n");
printf("\t*******************************\n");
switch(i){
case1:
printf("PrintBin_treePreorder:
");
break;
case2:
printf("PrintBin_TreeInorder:
");
break;
case3:
printf("PrintBin_TreePostorder:
");
break;
求树的深度及叶
case4:
depth=TreeDepth(root);//
子数
number=%d",depth,NodeNum);
printf("BinTreeLeafnumber=%d",leaf);break;
case5:
printf("LevePrintBin_Tree:
");
Levelorder(root);//按层次遍历
break;default:
exit
(1);
}
printf("\n");
}while(i!
=0);
}
执行程序
1.先序遍历
1
PrintHin_treePi'eordei*:
abdhlnieJncfhog
2.中序遍历
PrintBin_TrecInander*Ihndibcnjafokcg
3.后序遍历
PrintBin^TreePostorder:
Inhidnjebokf^ca
4.结点数叶子数高度
ihlKtDtpth:
5BinlirteNocleBinTfteLeaf的瞄州%
5..层次遍历
LeuePi*intBin_Tree:
己bcdefghijklmno
自己设计的:
abdhl##m##i##e#jn###cf#ko###g##
1.预计先序遍历结果:
abdhlmiejncfkog
2.预计中序遍历结果:
lhmdibenjafokcg
3.预计后序遍历结果:
lmhidnjebokfgca
4结点数15高度5叶子数6
实际结果:
CreatBin_Tree;Inputpveordei*=Jntt4l4tcf
XKXXXXXXJt*selecthhxxnnjcjcxhhh1:
Preoi*(lepTpauep-sa.!
2=lorderIraucrsal3:
PoEtor-dertrauei'sal4:
PosCTpeeDepthsNodenunbei*-^Le^.fnumhei'5:
LeuelDepthS:
Exit
1PrintBin_treePreorder-:
abtihlnxeJncfkog*2PrintBinjreeInorder:
Ihmdibcnjafokcg-3PrintBin_TreePostupdee:
ImhidnJebokfgca4BinTreeDeptli=5BinTr-eeNodemirnbe1^=15BinTreeLeafnuiriber-^fi5LevePrintBlnjree:
ahcdefsfhijklmno0Pressanvkeytocontinue-
实验心得:
这次实验主要是要让我们熟练树及其相关知识熟练掌握
先序中序后序遍历,层次遍历然后我们白己画一个图会实现以上功能以及叶子数结点数还有高度的计算程序里面大量运用了递归以及队的应用,
实验三、图的遍历操作
一、目的
掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储结构;掌握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"stdio.h”
#include"stdlib.h”
#defineMaxVertexNum100//定义最大顶点数
typedefstruct{
charvexs[MaxVertexNum];//顶点表
intedges[MaxVertexNum][MaxVertexNum];//邻接矩阵,可
看作边表
intn,e;//图中的顶点数n和边数e
}MGraph;//用邻接矩阵表示的图的类型
//=========建立邻接矩阵=======
voidCreatMGraph(MGraph*G)
{
inti,j,k;
chara;
printf("InputVertexNum(n)andEdgesNum(e):
");
scanf("%d,%d",&G->n,&G->e);//输入顶点数和边数
scanf("%c”,&a);
printf("InputVertexstring:
");
for(i=0;in;i++)
scanf("%c”,&a);
G->vexs[i]=a;//读入顶点信息,建立顶点表
}
for(i=0;in;i++)
for(j=0;jn;j++)
G->edges[i][j]=0;//初始化邻接矩阵
printf("Inputedges,CreatAdjacencyMatrix\n");
for(k=0;ke;k++)(//读入e条边,建立邻接矩阵
scanf("%d%d",&i,&j);//输入边(Vi,Vj)的顶点序号
G->edges[i][j]=1;
G->edges[j][i]=1;//若为无向图,矩阵为对称矩阵;若建立有
向图,去掉该条语句
}
}
//=========定义标志向量,为全局变量=======
typedefenum{FALSE,TRUE}Boolean;
Booleanvisited[MaxVertexNum];
//========DFS:
深度优先遍历的递归算法======
voidDFSM(MGraph*G,inti)
{//以Vi为出发点对邻接矩阵表示的图G进行DFS搜索,邻接矩阵
是0,1矩阵
intj;
printf("%c",G->vexs[i]);//
visited[i]=TRUE;//
for(j=0;jn;j++)//
if(G->edges[i][j]==1&&!
visited[j])
DFSM(G,j);//
过,故Vj为新出发点
}
voidDFS(MGraph*G)
{
inti;
for(i=0;in;i++)
visited[i]=FALSE;//
for(i=0;in;i++)
if(!
visited[i])//Vi
DFSM(G,i);//
}
//===========BFS广度优先遍历=
voidBFS(MGraph*G,intk)
访问顶点Vi
置已访问标志
依次搜索Vi的邻接点
(Vi,Vj)CE,且Vj未访问
标志向量初始化
未访问过
以Vi为源点开始DFS搜索
{//以Vk为源点对用邻接矩阵表示的图G进行广度
优先搜索
inti,j,f=0,r=0;
intcq[MaxVertexNum];//
for(i=0;in;i++)
visited[i]=FALSE;//
for(i=0;in;i++)
cq[i]=-1;//
printf("%c",G->vexs[k]);//visited[k]=TRUE;
cq[r]=k;//Vk
将其序号入队
while(cq[f]!
=-1)(//
i=cq[f];f=f+1;//Vf
for(j=0;jn;j++)//
定义队列
标志向量初始化
队列初始化
访问源点Vk
已访问,将其入队。
注意,实际上是
队非空则执行
出队
依次Vi的邻接点Vj
if(G->edges[i][j]==1&&!
visited[j])(//Vj
访问
printf("%c",G->vexs[j]);//访问Vj
visited[j]=TRUE;r=r+1;cq[r]=j;//访问过Vj入队
}}}//==========main=====voidmain()
inti;
MGraph*G;
G=(MGraph*)malloc(sizeof(MGraph));//为图G申请内存空
间
CreatMGraph(G);//
printf("PrintGraphDFS:
");
DFS(G);//
printf("\n");
printf("PrintGraphBFS:
");
BFS(G,3);//
历
建立邻接矩阵
深度优先遍历
以序号为3的顶点开始广度优先遍
printf("\n");
调试结果:
白己画的图:
1对应顶点下标0以此类推9对应下标8
预计运行结果:
DFS:
012345678
BFS:
324105687
对应我这个图:
DFS:
123456789
BFS:
435216798
实验心得:
图在数据结构中是相当重要的一部分联系很多现实问题
图的根本就是顶点和边通过顶点和边建立邻接矩阵以及邻接链表广度搜索和深度搜索是此算法着重关注的地方。
要学会白己画图然
后写出这两种搜索的结果,程序中用了队的算法是亮点通过TRUE和FAUSE来标记顶点是否以及访问避免重复
实验四、排序
一、目的
掌握各种排序方法的基本思想、排序过程、算法实现,能进行时
间和空间性能的分析,根据实际问题的特点和要求选择合适的排序方法。
二、要求
实现直接排序、冒泡、直接选择、快速、堆、归并排序算法。
比
较各种算法的运行速度。
三、程序示例
#include"stdio.h”
#include"stdlib.h”
#defineMax100//假设文件长度
typedefstruct{//定义记录类型
intkey;//关键字项
}RecTy