版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
课程实验报告课程名:数据结构
目录TOC\o"1-3"\h\u18974实验一单链表队列 321369实验二顺序数组 1223558实验三顺序二叉树 172868实验四链式二叉树 2716151实验五图 3319286实验六拓扑排序 4010834实验七静态查找表 4820453实验八二叉排序树 6528290实验九折半排序、二路插入排序,表插入排序 72
南昌大学实验报告实验一单链表队列学生姓名:xx学号:xxxxxxxx专业班级:计算机185实验类型:□验证□综合□设计□创新实验日期:2019-10-10实验成绩:实验项目名称用顺序表实现学生健康情况登记表。实验目的掌握非循环队列的逻辑结构、存储结构、操作。利用单链表实现非循环队列,用C++编写程序实现简单的控制台交互界面。实验基本原理非循环的队列特点是先进先出。使用队头指针front和队尾指针rear来进行对队列的元素的插入删除操作。主要仪器设备及耗材PC微型计算机,C++集成开发环境编译器。实验步骤(完整内容见光盘)问题分析与程序设计问题分析非循环队列是一个有着特定操作的单链表,特点只能操作队头和队尾的元素。应当允许进行队尾元素的插入,队头元素的删除,打印队列等基本操作。算法原理利用单链表可以创建一个理论上无限长的单链表队列。队尾元素插入的对应操作是生成一个新的节点,类比于单链表的元素插入操作,将新节点插入队列末尾。队头元素的删除则类比于单链表的删除元素的操作,将队头节点内存释放,队头指针指向下一个节点。代码#include
<iostream>
#include
<string>
#include
<windows.h>
using
namespace
std;
#define
OK
1
#define
ERROR
0
#define
TRUE
1
#define
FALSE
0
typedef
int
Status;
struct
ElemType
{
string
name;
int
value;
};
typedef
struct
QNode
{
ElemType
data;
QNode
*next;
}
QNode,
*QueuePtr;
struct
LinkQueue
{
QueuePtr
rear,
front;
int
length;
};
//基本操作的函数
//创建一个队列
Status
InitQueue(LinkQueue
&Q)
{
QueuePtr
baseNode;
baseNode
=
new(QNode);
Q.front
=
baseNode;//头
Q.rear
=
baseNode;//尾
Q.length
=
0;
return
OK;
}
//销毁一个队列
Status
DestroyQueue(LinkQueue
&Q)
{
if
(!Q.front)
return
ERROR;
QueuePtr
cur_Node,
next_Node;
cur_Node
=
Q.front->next;
next_Node
=
cur_Node->next;
while
(cur_Node
!=
Q.rear)
{
delete
(cur_Node);
cur_Node
=
next_Node;
next_Node
=
cur_Node->next;
}//释放所有结点内存
Q.rear
=
NULL;
Q.front
=
NULL;
return
OK;
}
//清空一个队列
Status
ClearQueue(LinkQueue
&Q)
{
if
(!Q.front)
return
ERROR;
QueuePtr
cur_Node,
next_Node,
firstNode;
cur_Node
=
Q.front->next;
next_Node
=
cur_Node->next;
while
(cur_Node
!=
Q.rear)
{
delete
(cur_Node);
cur_Node
=
next_Node;
next_Node
=
cur_Node->next;
}//释放所有结点内存
if
(firstNode
=
new(QNode))
{
Q.front
=
firstNode;//头
Q.rear
=
firstNode;//尾
Q.length
=
0;
}
return
OK;
}
//查询队列是否为空
Status
QueueEmpty(LinkQueue
Q)
{
if
(Q.front
==
Q.rear
||
Q.length
==
0)
return
TRUE;
else
return
FALSE;
}
//返回队列的长度
int
QueueLength(LinkQueue
Q)
{
return
Q.length;
}
//获取队头元素
Status
GetHead(LinkQueue
Q,
ElemType
&e)
{
if
(!Q.front
&&
Q.length
!=
0)
return
ERROR;
=
Q.front->next->;
e.value
=
Q.front->next->data.value;
return
OK;
}
//插入新元素
Status
EnQueue(LinkQueue
&Q,
ElemType
e)
{
if
(!Q.rear)return
ERROR;
QueuePtr
newNode;
newNode
=
new(QNode);
newNode->
=
;
newNode->data.value
=
e.value;
Q.rear->next
=
newNode;
Q.rear
=
newNode;
Q.length++;
return
OK;
}
//删除队头元素(若队列不为空),用e返回队头元素
Status
DeQueue(LinkQueue
&Q,
ElemType
&e)
{
if
(Q.length
==
0)return
ERROR;
QueuePtr
cur_Node;
cur_Node
=
Q.front->next;
=
cur_Node->;
e.value
=
cur_Node->data.value;
Q.front
=
cur_Node->next;
delete
(cur_Node);
return
OK;
}
//
打印所有元素
Status
visitQueue(LinkQueue
Q)
{
if
(Q.front
==
Q.rear)
return
ERROR;
QueuePtr
cur_Node;
cur_Node
=
Q.front->next;
int
i
=
1;
while
(cur_Node
!=
Q.rear)
{
cout
<<
"结点Node"
<<
i
<<
"的"
<<
endl
<<
"name:"
<<
cur_Node->
<<
endl
<<
"value:"
<<
cur_Node->data.value
<<
endl;
i++;
cur_Node
=
cur_Node->next;
}
cout
<<
"结点Node"
<<
i
<<
"的"
<<
endl
<<
"name:"
<<
cur_Node->
<<
endl
<<
"value:"
<<
cur_Node->data.value
<<
endl;
return
OK;
}
int
main()
{
ElemType
var,U_var;
LinkQueue
Q;
int
exit_code
=
-1;
while
(exit_code
!=
10)
{
Sleep(1000);
cout
<<
"1.创造一个队列"
<<
endl
<<
"2.销毁一个队列"
<<
endl
<<
"3.清空队列"
<<
endl
<<
"4.查询队列是否为空"
<<
endl
<<
"5.返回队列的长度"
<<
endl
<<
"6.返回队头元素"
<<
endl
<<
"7.插入队尾元素"
<<
endl
<<
"8.删除队头元素"
<<
endl
<<
"9.打印队列所有元素"
<<
endl
<<
"10.退出"
<<
endl
<<
"输入对应的操作码选择对应的功能!"
<<
endl;
while
(!(cin
>>
exit_code)
||
cin.fail()
||
exit_code
>
10)
{
cin.clear();
cin.sync();
cout
<<
"输入错误,请重新输入!"
<<
endl;
}
switch
(exit_code)
{
case
1:
if
(InitQueue(Q))
{
=
"张三";
var.value
=
1;
EnQueue(Q,
var);
=
"李四";
var.value
=
2;
EnQueue(Q,
var);
=
"王五";
var.value
=
3;
EnQueue(Q,
var);
}
{
if
(visitQueue(Q))cout
<<
"操作成功!"
<<
endl;
};
break;
case
2:
if
(DestroyQueue(Q))
cout
<<
"操作成功!"
<<
endl;
break;
case
3:
if
(ClearQueue(Q))
cout
<<
"操作成功!"
<<
endl;
break;
case
4:
if
(QueueEmpty(Q))
cout
<<
"队列为空!"
<<
endl;
else
cout<<"队列不为空!"<<endl;
break;
case
5:
if
(QueueLength(Q))
cout
<<
"Q.length
is
:"
<<
QueueLength(Q)
<<
endl
<<
"操作成功!"
<<
endl;
break;
case
6:
if
(GetHead(Q,
var))
{
cout
<<
"操作成功!"
<<
endl
<<
"H
is:"
<<
<<endl
<<
"Head.value
is:"
<<
var.value
<<
endl;
}
break;
case
7:
cout<<"input
name:"<<endl;
cin>>U_;
cout<<"input
value:"<<endl;
cin>>U_var.value;
if
(EnQueue(Q,U_var))
cout
<<
"操作成功!"
<<
endl;
break;
case
8:
if
(DeQueue(Q,var))
cout
<<
"操作成功!"
<<
endl
<<
"H
is:"
<<
<<endl
<<
"Head.value
is:"
<<
var.value
<<
endl;
break;
case
9:
if
(visitQueue(Q))
{
cout
<<
"操作成功!"
<<
endl;}
break;
}
}
return
0;
}
实验数据及处理结果初始菜单页面创建一个队列查队列是否为空返回队列长度返回队头元素插入队尾元素删除队头元素思考讨论题或体会或对改进实验的建议利用队列的特性可以设计一个基于队列原理的银行/医院领号排队系统。利用非循环队列模拟银行用户的排队情况,可以借此分析银行的业务办理高峰期,用户平均排队时间等信息,可以方便银行进行业务优化。可以看见,掌握了数据结构的基本方法,我们还要善于运用创新思维,学以致用,结合生活实际把书本上抽象的知识具体起来。八、参考资料《数据结构》
南昌大学实验报告实验二顺序数组学生姓名:xx学号:xxxxxxxx专业班级:计算机185班实验类型:□验证□综合□设计□创新实验日期:2019-10-17实验成绩:实验项目名称自定义数组及其常规操作实验目的用自己定义的数据类型构造一个新数据类型的顺序数组。实现顺序数组的基本操作:初始化,赋值,取值,删除。实验基本原理1.顺序数组可以看成一个定长的顺序链表。在确定了里面数据的约束关系后就可以为数组分配内存空间并进行相应的操作。四、主要仪器设备及耗材PC微型计算机,C++集成开发环境编译器。五、实验步骤(完整内容见光盘)1.问题分析:本次实验只需要实现数组的几个基本操作:初始化,赋值,取值,删除。由于使用了不定参数传参方式,所以不方便设计用户交互界面,只能实现基本功能。2.代码#define
MAX_ARRAY_DIM
8
#define
ERROR
0
#define
OVERFLOW
-2
#define
OK
1
typedef
int
Status;
typedef
int
ElemType;
typedef
struct
{
ElemType
*base;
int
dim;
int
*bounds;
int
*constants;
}Array;
Status
Array_Operation::InitArray(Array
&A,
int
dim,
...)
{
if(dim
<1||dim
>
MAX_ARRAY_DIM)
return
ERROR;
A.dim
=
dim;
A.bounds
=
new
(int)(dim);
if(!A.bounds)
exit(OVERFLOW);
int
elemtotal
=
1;
va_list
ap;
va_start(ap,dim);
for
(int
i
=
0;i<dim;i++){
A.bounds[i]=
va_arg(ap,int);
if(A.bounds[i]<0)
return
OVERFLOW;
elemtotal*=A.bounds[i];
}
va_end(ap);
A.base
=
(ElemType
*)malloc(elemtotal*
sizeof(ElemType));
//A.base
=
new
(ElemType)(elemtotal);
if(!A.base)
exit(OVERFLOW);
A.constants
=
new(int)(dim);
if(!A.constants)
exit(OVERFLOW);
A.constants[dim-1]
=
1;
for
(int
i
=
dim-2;i>=0;--i){
A.constants[i]
=
A.bounds[i+1]*A.constants[i+1];
}
return
OK;
}
Status
Array_Operation::DestroyArray(Array
&A)
{
if(!A.base)return
ERROR;
free(A.base);A.base
=
NULL;
if(!A.bounds)
return
ERROR;
free(A.bounds);A.bounds
=
NULL;
if(!A.constants)
return
ERROR;
free(A.constants);A.constants
=NULL;
return
OK;
}
Status
Locate(Array
A,va_list
ap,int
&off){
off
=
0;
for
(int
i
=0;i<A.dim;++i){
int
ind
=
va_arg(ap,int);
if(ind
<0||ind>=A.bounds[i])
return
OVERFLOW;
off
+=
A.constants[i]*ind;
}
return
OK;
}
Status
Array_Operation::Value(Array
A,
ElemType
&e,
...)
{
va_list
ap;
va_start(ap,e);
int
result=0;
int
off;
if((result
=
Locate(A,ap,off)<=0))
return
result;
e
=
*(A.base+off);
return
OK;
}
Status
Array_Operation::Assign(Array
&A,
ElemType
e,
...)
{
va_list
ap;
va_start(ap,e);
int
result=0;
int
off;
if((result
=
Locate(A,ap,off)<=0))
return
result;
va_end(ap);
*(A.base+off)
=
e;
return
OK;
}
#include
<iostream>
#include
<stdarg.h>
#include
"Statement.h"
#include
"Array_OPeration.h"
#include
<windows.h>
using
namespace
std;
int
main()
{
Array
A;
int
dim;
ElemType
e
,e2;
e
=
666;
int
bounds[MAX_ARRAY_DIM];
Array_Operation
AO;
int
exit_code
=
-1;
while
(exit_code
!=
10)
{
Sleep(1000);
cout
<<
"1.初始化数组"
<<
endl
<<
"2.删除数组"
<<
endl
<<
"3.数组赋值"
<<
endl
<<
"4.数组取值"
<<
endl
<<
"5.退出"
<<
endl
<<
"10.退出"
<<
endl
<<
"输入对应的操作码选择对应的功能!"
<<
endl;
while
(!(cin
>>
exit_code)
||
cin.fail()
||
exit_code
>
10)
{
cin.clear();
cin.sync();
cout
<<
"输入错误,请重新输入!"
<<
endl;
}
switch
(exit_code)
{
case
1:
if
(AO.InitArray(A,
3,
3,
3,
3))cout
<<
"数组初始化成功!"
<<
endl;
break;
case
2:
if(AO.DestroyArray(A))
cout<<"数组初始化删除成功!"<<endl;
break;
case
3:
if(AO.Assign(A,e,0,1,1))
cout<<"赋值成功!"<<endl;
break;
case
4:
if(AO.Value(A,e2,0,1,1)){
cout<<"取值成功!取到的值是:"<<e2<<endl;
}
break;
}
}
return
0;
}
实验数据及处理结果数组初始化数组赋值数组取值思考讨论题或体会或对改进实验的建议自定义的顺序数组只能实现简单的操作。用链表实现数组可以丰富数组的功能,例如实现不定长度的数组,或者构造不规则的多维数组,更可以引申为矩阵。基本的数据结构只是提供了底层原理和基础操作的实现。我们可以根据实际需要或者自己的理解,从基础操作入手,将简单的方法演化为更高级的功能。参考资料《数据结构》
南昌大学实验报告实验三顺序二叉树学生姓名:xx学号:xxxxxxxx专业班级:计算机185班实验类型:□验证□综合□设计□创新实验日期:2019-11-7实验成绩:实验项目名称顺序二叉树及其基本操作实验目的建立顺序二叉树并实现基本操作:1.求树的深度2.求树的节点数3.打印二叉树4.二叉树左右节点互换。实验基本原理采用数组的方式存储二叉树,二叉树各节点的关系由其对应的下标之间的数学关系判定。即存在下标为i存在有效节点n1,若下标为2i存在有效节点n2,下标2i+1存在有效节点n3,则n2为n1的左子节点,n3为n1的右子节点。主要仪器设备及耗材PC微型计算机,C++集成开发环境编译器。实验步骤(完整内容见光盘)问题分析与程序设计树的有效节点数可以通过遍历存储二叉树的数组,记录有效节点实现。求树的深度可以通过判断最后一个节点所在的区间范围,即求出2k-1~2k,则k为这棵树的最大深度。二叉树的左右节点互换则是在每一层中,将该层对应的节点互换即可。打印二叉树则要计算好对应的空格与树枝,逐层打印。源代码/**
*
程序采用了动态建立数组的方式,程序在C14或更新的cpp编译环境下才能正常运行
*
*/
#include
<iostream>
#include
<iomanip>
#include
<cmath>
#include
<cstring>
using
namespace
std;
#define
ERROR
0
#define
OK
1
typedef
int
Status;
#define
MAX_TREE_SIZE
100
struct
SqBiTree
{
string
NodeName="empty";
int
use=0;
};
struct
info
{
string
NodeName;
int
r_child
=
0;
int
l_child
=
0;
};
class
SequenceBinaryTree
{
public:
int
Locate(SqBiTree
T[],
string
NodeName)
{
for
(int
i
=
1;
i
<
MAX_TREE_SIZE;
i++)
{
if
(T[i].NodeName
==
NodeName)
{
return
i;
}
}
return
ERROR;
}
Status
InitBiTree(SqBiTree
T[])
{
for
(int
j
=
0;
j
<
MAX_TREE_SIZE;
j++)
{
T[j].NodeName
=
"empty";
T[j].use
=
0;
}//数组初始化
int
i
=
1;
string
s
=
"OK";
string
user_input;//输入信息
string
parent;//双亲节点的信息
string
child_flag;//判断是否为左/右孩子
string
NodeName;//孩子节点的信息
int
index
=
1;
while
(s
!=
"END"
&&
s
!=
"end")
{
cout
<<
"请输入顺序二叉树各个节点的信息:"
<<
"(少于"
<<
MAX_TREE_SIZE
<<
"个节点)"
<<
endl;
cout
<<
"输入END结束!"
<<
endl;
cout
<<
"输入样例:A
L
B"
<<
endl
<<
"其中:A是要输入的节点的双亲节点"
<<
endl
<<
"L指定是左节点还是右节点"
<<
endl
<<
"B是新节点的名称"
<<
endl;
if
(index
==
1)
cout
<<
"头节点的双亲节点,左右子节点的标记
可以用空格代替"
<<
endl;
getline(cin,user_input);
s
=
user_input;
parent
=
user_input[0];
child_flag
=
user_input[2];
NodeName
=
user_input[4];
if
(parent
==
"
"
&&
child_flag
==
"
")
{
T[index].use
=
1;
T[index].NodeName
=
NodeName;
}
else
if
(child_flag
==
"L")
{
index
=
Locate(T,
parent);
T[2
*
index].use
=
1;
T[2
*
index].NodeName
=
NodeName;
}
else
if
(child_flag
==
"R")
{
index
=
Locate(T,
parent);
T[2
*
index
+
1].use
=
1;
T[2
*
index
+
1].NodeName
=
NodeName;
}
}
return
OK;
}
Status
InitBiTree_Default(SqBiTree
T[])
{
string
s
=
"ABCDEFGHIJKLMNO";
for
(int
j
=
0;
j
<
MAX_TREE_SIZE;
j++)
{
T[j].NodeName
=
"empty";
T[j].use
=
0;
}
for
(int
i
=
1;
i
<
16;
i++)
{
T[i].use
=
1;
T[i].NodeName
=
s[i
-
1];
}
T[18].use
=
1;
T[18].NodeName
=
"Q";
T[20].use
=
1;
T[20].NodeName
=
"W";
return
OK;
}
Status
GetNodeNum(SqBiTree
T[])
{
int
count
=
0;
for
(int
i
=
1;
i
<
MAX_TREE_SIZE;
i++)
{
if
(T[i].NodeName
!=
"empty"
&&
T[i].use)
{
count++;
}
}
return
count;
}
Status
GetTreeDepth(SqBiTree
T[])
{
int
final_index
=
0;
int
k
=
0;
for
(int
i
=
1;
i
<
MAX_TREE_SIZE;
i++)
{
if
(T[i].NodeName
!=
"empty"&&T[i].use)
{
final_index
=
i;
}
}//找最后一个节点的下标
for
(k
=
1;
k
<
MAX_TREE_SIZE;
k++)
{
if
(final_index
<=
pow(2,
k))
{
break;
}
}//用下标求深度
return
k;
}
Status
NodeExchange(SqBiTree
T[],
int
index)
{
int
depth
=
GetTreeDepth(T);
if
(depth
==
1)
return
OK;
else
{
for
(int
nD
=
2;
nD
<=
depth;
nD++)
{
for
(int
k
=
pow(2,
nD
-
1);
k
<
pow(2,
nD)
-
pow(2,
nD
-
2);
k++)
{
swap(T[k],
T[int(pow(2,
nD)
-
(k
-
pow(2,
nD
-
1)
+
1))]);
}
}
}
return
OK;
}
Status
calBase(int
depth,
int
nD,
int
layer[])
{
int
n
=
3;
//
int
result
=
0;
if
(depth
-
nD
==
1)
return
n
+
1;
for
(int
i
=
1;
i
<=
depth
-
nD;
i++)
{
for
(int
k
=
1;
k
<
i;
k++)
{
if
(k
==
1)
n
=
0;
n
+=
layer[k]
+
1;
}
layer[i]
=
n;
}
for
(int
i
=
1;
i
<=
depth
-
nD;
i++)
{
result
+=
layer[i];
}
return
result
+
depth
-
nD;
}
Status
printSpace(int
i)
{
for
(int
j
=
0;
j
<
i;
j++)
{
cout
<<
"
";
}
return
OK;
}
Status
printUnderline(int
i)
{
for
(int
j
=
0;
j
<
i;
j++)
{
cout
<<
"_";
}
return
OK;
}
Status
printBiTree(SqBiTree
T[])
{
int
Base;//每一层的基准
int
nD;//记录当前层数
int
temp
=
0;//临时变量
int
depth
=
GetTreeDepth(T);//树的总深度
int
Node_num
=
GetNodeNum(T);//树的节点数
int
layer[depth
+
1];//每一层的树枝信息
info
Node_info[Node_num];
for
(int
i
=
1;
i
<
Node_num;
i++)
{
if
(T[i].NodeName
!=
"empty"
&&
T[i].use)
{
if
(T[2
*
i].use)
Node_info[i].l_child
=
1;
if
(T[2
*
i
+
1].use)
Node_info[i].r_child
=
1;
}
}//记录每个节点的左右孩子信息
for
(nD
=
1;
nD
<
depth;
nD++)
{
//每层的第一部分,先打节点
int
count
=
1;
for
(int
k
=
pow(2,
nD
-
1);
k
<
pow(2,
nD);
k++)
{
//计算当前层数的基准空格
Base
=
calBase(depth,
nD,
layer);
if
(count
==
1)
{
printSpace(Base);
if
(T[k].NodeName
!=
"empty"
&&
T[k].use)
{
cout
<<
T[k].NodeName;
}
else
{
cout
<<
"
";
}
count++;
continue;
}
printSpace(2
*
Base
+
1);
if
(T[k].NodeName
!=
"empty"
&&
T[k].use)
{
cout
<<
T[k].NodeName;
}
else
{
cout
<<
"
";
}
}
cout
<<
endl;
//
//每层的树枝1
count
=
1;
for
(int
k
=
pow(2,
nD
-
1);
k
<
pow(2,
nD);
k++)
{
//计算当前层数的基准空格
Base
=
calBase(depth,
nD,
layer);//节点的基准偏移
int
Base2
=
Base
-
layer[depth
-
nD];//树枝的基准偏移
if
(count
==
1)
{
printSpace(Base2);
if
(Node_info[k].l_child)
{
printUnderline(layer[depth
-
nD]
-
1);
cout
<<
"/";
}
else
printSpace(layer[depth
-
nD]);
//如果有左子节点
printSpace(1);
if
(Node_info[k].r_child)
{
cout
<<
"\\";
printUnderline(layer[depth
-
nD]
-
1);
}
else
printSpace(layer[depth
-
nD]);//如果有右子节点
printSpace(2
*
Base2
+
1);
count++;
continue;
}
if
(Node_info[k].l_child)
{
printUnderline(layer[depth
-
nD]
-
1);
cout
<<
"/";
}
else
printSpace(layer[depth
-
nD]);
//如果有左子节点
printSpace(1);
if
(Node_info[k].r_child)
{
cout
<<
"\\";
printUnderline(layer[depth
-
nD]
-
1);
}
else
printSpace(layer[depth
-
nD]);//如果有右子节点
printSpace(2
*
Base2
+
1);
count++;
}
cout
<<
endl;
}
//下面打印最底层的节点
int
count_final_layer
=
1;
for
(int
k
=
pow(2,
nD
-
1);
k
<
pow(2,
nD);
k++)
{
if
(count_final_layer
==
1)
{
if
(T[k].NodeName
!=
"empty"
&&
T[k].use)
{
cout
<<
T[k].NodeName;
}
else
{
cout
<<
"
";
}
count_final_layer++;
printSpace(7);
continue;
}
if
(T[k].NodeName
!=
"empty"
&&
T[k].use)
{
cout
<<
T[k].NodeName;
}
else
{
cout
<<
"
";
}
if
(count_final_layer
%
2
==
0)
{
printSpace(1);
}
else
{
printSpace(7);
}
count_final_layer++;
}
return
OK;
}
};
int
main()
{
SqBiTree
T[MAX_TREE_SIZE];
SequenceBinaryTree
SBT;
cout
<<
"使用预设方案:"
<<
endl;
SBT.InitBiTree_Default(T);
cout<<"当前的二叉树为:"<<endl;
SBT.printBiTree(T);
cout
<<
endl
<<
"当前二叉树的节点数是:"
<<
SBT.GetNodeNum(T)
<<
endl;
cout
<<
"当前二叉树的深度是:"
<<
SBT.GetTreeDepth(T)
<<
endl;
cout
<<
"将二叉树的左右节点互换:"
<<
endl;
SBT.NodeExchange(T,
1);
cout
<<
"二叉树左右节点互换后的结果为:"
<<
endl;
SBT.printBiTree(T);
return
0;
}
实验数据及处理结果二叉树的创建。求二叉树的节点数求二叉树的深度二叉树左右节点互换用户输入版思考讨论题或体会或对改进实验的建议实验体会:本次实验的难点在于实现打印二叉树。因为要考虑打印二叉树的树枝部分,所以要提前计算好基准空格数,根据基准空格数才能正确的计算出二叉树的各个树枝的打印宽度。在计算基准空格时,要注意每一层的基准空格数可以利用动态规划从最底层开始地推求出,这样才能保证打印的二叉树规整有序。八、参考资料《数据结构》 南昌大学实验报告实验四链式二叉树学生姓名:xx学号:xxxxxxxx专业班级:计算机185班实验类型:□验证□综合□设计□创新实验日期:2019-11-14实验成绩:一、实验项目名称链式二叉树的创建与遍历。二、实验目的实现分别采用先序方式创建二叉树,并实现二叉树的先序,中序,后序遍历。三、实验基本原理采用先序方式创建链式二叉树,树的各个节点的关系由各个节点的指针指向界定。所以每个节点的指针域要指明为左子节点,右子节点,双亲节点。先序遍历定义为:先访问根节点,再先序遍历左子树,再先序遍历右子树。中序遍历的定义为:先中序遍历左子树,再访问根节点,再中序遍历右子树。后序遍历的定义为:先后序遍历左子树,再后序遍历右子树,再访问根节点。四、主要仪器设备及耗材PC微型计算机,C++集成开发环境编译器。五、实验步骤(完整内容见光盘)问题分析与程序设计二叉树是递归定义的,所以有关二叉树的操作,例如二叉树的创建,遍历,核心思想都是递归。所以创建二叉树时可以采用递归方式依次创建每个节点的左右子节点。而前序中序后序遍历的区别在于打印节点的时机不同。递归的核心思想与栈相类似,为了避免二叉树的深度过深而出现的栈溢出问题,可以用栈代替递归,同样实现二叉树的前序中序和后序遍历。源代码#include
<iostream>
#include
<stack>
using
namespace
std;
typedef
int
Status;
#define
OK
1
#define
ERROR
0
typedef
string
TElemType;
typedef
struct
BitNode
{
string
data
=
"
";
BitNode
*lChild
=
NULL,
*rChild
=
NULL,
*parent
=
NULL;
}
*BitTree;
Status
Visit(BitTree
e)
{
if
(e
&&
e->data
!=
"
")
{
cout
<<
e->data
<<
"
";
return
OK;
}
return
ERROR;
}
class
BitTreeOperation
{
public:
//
创建二叉树
Status
CreatBitTree(BitTree
T,
BitTree
&T_child,
int
i)
{
cout
<<
"输入一个结点(输入END结束):"
<<
endl;
string
NodeName;
if
(i
==
1)
{
cout
<<
"输入"
<<
T->data
<<
"的左子节点,空格表示无该子节点:"
<<
endl;
}
else
if
(i
==
2)
{
cout
<<
"输入"
<<
T->data
<<
"的右子节点,空格表示无该子节点:"
<<
endl;
}
getline(cin,
NodeName);
if
(NodeName
==
"END")
return
OK;
if
(NodeName
==
"
")
T_child
=
NULL;
else
{
T_child
=
new(BitNode);
T_child->data
=
NodeName;
CreatBitTree(T_child,
T_child->lChild,
1);
CreatBitTree(T_child,
T_child->rChild,
2);
}
return
OK;
}
//
前序遍历
Status
PreOrderTraverse(BitTree
T,
Status
(*Visit)(BitTree
e))
{
if
(T)
{
if
(Visit(T))
{
if
(PreOrderTraverse(T->lChild,
Visit))
if
(PreOrderTraverse(T->rChild,
Visit))
return
OK;
}
return
ERROR;
}
else
return
OK;
}
Status
PreOrderTraverse_R(BitTree
T,
Status
(*Visit)(BitTree
e))
{
stack
<BitTree>
s;
while
(T
||
!s.empty())
{
while
(T)
{
Visit(T);
s.push(T);
T
=
T->lChild;
}
if
(!s.empty())
{
T
=
s.top();
s.pop();
T
=
T->rChild;
}
}
return
OK;
}
//
中序遍历
Status
InOrderTraverse(BitTree
T,
Status
(*Visit)(BitTree
e))
{
if
(T)
{
if
(InOrderTraverse(T->lChild,
Visit))
{
if
(Visit(T))
if
(InOrderTraverse(T->rChild,
Visit))
return
OK;
}
}
else
return
OK;
}
Status
InOrderTraverse_R(BitTree
T,
Status
(*Visit)(BitTree
e))
{
stack
<BitTree>
s;
while
(T
||
!s.empty())
{
while
(T)
{
s.push(T);
T
=
T->lChild;
}
if
(!s.empty())
{
T
=
s.top();
s.pop();
Visit(T);
T
=
T->rChild;
}
}
return
OK;
}
//
后序遍历
Status
PostOrderTraverse(BitTree
T,
Status
(*Visit)(BitTree
e))
{
if
(T)
{
PostOrderTraverse(T->lChild,
Visit);
PostOrderTraverse(T->rChild,
Visit);
Visit(T);
}
else
return
OK;
}
Status
PostOrderTraverse_R(BitTree
T,
Status
(*Visit)(BitTree
e))
{
stack<BitTree>
s1,s2;
while(T
||
!s1.empty())
{
while(T)
{
s2.push(T);
s1.push(T);
T
=
T->rChild;
}
if
(!s1.empty())
{
T
=
s1.top();
s1.pop();
T
=
T->lChild;
}
}
while(!s2.empty())
//访问(打印)S2中元素
{
T
=
s2.top();
s2.pop();
cout<<T->data;
}
}
};
int
main()
{
BitTreeOperation
BTO;
TElemType
e;
BitTree
T;
T
=
new(BitNode);
BTO.CreatBitTree(T,
T,
0);
cout
<<
"前序遍历:";
BTO.PreOrderTraverse(T,
Visit);
cout
<<endl<<
"前序遍历(非递归形式):";
BTO.PreOrderTraverse_R(T,
Visit);
cout
<<
endl
<<
"中序遍历:";
BTO.InOrderTraverse(T,
Visit);
cout
<<
endl
<<
"中序遍历(非递归形式):";
BTO.InOrderTraverse_R(T,
Visit);
cout
<<
endl
<<
"后序遍历:";
BTO.PostOrderTraverse(T,
Visit);
cout
<<
endl
<<
"后序遍历(非递归形式):";
BTO.PostOrderTraverse_R(T,
Visit);
return
0;
}
六、实验数据及处理结果二叉树的创建。二叉树的前序、中序、后序遍历。七、思考讨论题或体会或对改进实验的建议实验体会:递归是代码中一种比较特别的形式。代码虽少,核心思想却很难理解。然而二叉树的定义就是用递归思想实现,因此本次实验中涉及的操作都用了递归的思想。使用递归最关键的是递归结束条件,以及递归回溯时各个值的变化。这次实验中,实现前序、中序、后序遍历的函数形态上很相似,区别仅仅在于打印节点信息的位置不同。但是仅仅是位置上的细微区别,就是算法核心上的本质区别。八、参考资料《数据结构》 南昌大学实验报告实验五图学生姓名:xx学号:xxxxxxxx专业班级:计算机185班实验类型:□验证□综合□设计□创新实验日期:2019-11-21实验成绩:一、实验项目名称图的建立与遍历二、实验目的建立无向图并实现深度优先(DFS)遍历。三、实验基本原理无向图实质是有双向边的有向图。实验中对于图的存储采用邻接表的方式。深度优先(DFS)类似于先根遍历,注意要点是要把遍历过的根节点进行标记避免重复遍历。四、主要仪器设备及耗材PC微型计算机,C++集成开发环境编译器。五、实验步骤(完整内容见光盘)问题分析与程序设计本次实验程序有两个核心,一:根据用户输入创建对应的图,二:采用深度优先遍历用户创建的图并输出。其中,图的创建可以在程序中添加适当引导语句引导用户输入,图的保存采用邻接表的方式,具体保存方法可以根据图的类型不同而不同。深度优先遍历类似于树的先根遍历,为了避免重复遍历某些节点,可以采用创建额外的节点数组记录访问与否或在创建节点结构体时加入一个记录是否访问过的风向标。本次实验采取了第二种方法。源代码#include
<iostream>
#include
<string>
using
namespace
std;
#define
INFINITY
INT_MAX
//最大值
#define
MAX_VERTEX_NUM
20
//最大顶点个数s
typedef
int
Status;
#define
ERROR
0
#define
OK
1
typedef
string
VertextType;
//顶点关系类型
typedef
struct
DGArcNode
{
int
adjvex;//该弧所指向的顶点的位置
int
flag
=
0;
int
start,end;
DGArcNode
*nextarc
=
NULL;//指向下一条弧的指针
}
DGArcNode;
struct
DGVNode
{
VertextType
data;
int
flag
=
0;
DGArcNode
*firstarc
=
NULL;
};
typedef
DGVNode
*DGVNode_p,
DGAdjList[MAX_VERTEX_NUM];
typedef
struct
{
DGAdjList
vertices;
int
vexnum;//顶点数
int
arcnum;//弧数
int
kind;//种类
}
ALGraph;
class
Graph
{
public:
Status
Locate(DGAdjList
List,
string
c)
{
int
result;
for
(int
i
=
0;
i
<
MAX_VERTEX_NUM;
i++)
{
if
(List[i].dat
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025至2031年中国阶梯R型铁芯行业投资前景及策略咨询研究报告
- 2025-2030年中国高纯锰市场运行状况及发展趋势预测报告
- 2025-2030年中国香油(芝麻油)行业市场运营状况与发展潜力分析报告
- 2025-2030年中国重型搅拌车市场前景趋势展望及投资潜力分析报告
- 印刷品市场营销案例分析考核试卷
- 2025年度商标权授权使用合同
- 刀剪产品的用户体验改善措施考核试卷
- 2025年阳光房施工安全免责协议及施工安全风险评估合同
- 2025年度二零二五年度个人租赁公寓住房合同
- 中药材种植的药材种植效益分析考核试卷
- DB-T29-74-2018天津市城市道路工程施工及验收标准
- 小学一年级20以内加减法混合运算3000题(已排版)
- 智慧工厂数字孪生解决方案
- 病机-基本病机 邪正盛衰讲解
- 品管圈知识 课件
- 非诚不找小品台词
- 2024年3月江苏省考公务员面试题(B类)及参考答案
- 患者信息保密法律法规解读
- 老年人护理风险防控PPT
- 充电桩采购安装投标方案(技术方案)
- 医院科室考勤表
评论
0/150
提交评论