实验一 线性表的顺序表示与实现
1.实验目的
(1) 掌握线性表的顺序存储结构;
(2) 验证顺序表及其基本操作的实现;
(3) 掌握数据结构及算法的程序实现的基本方法。
2.实验内容
(1) 建立含有若干个元素的顺序表;
(2) 对已经建立的顺序表实现插入、删除、查找、合并等基本操作。
3.实现算法
首先,定义顺序存储结构如下:
Typedef struct {
Elemtype *elem;
Int length;
Int listsize;
}sqlist;
其次,建立含有n个元素的顺序表,算法如下:
Status InitList_Sq( SqList
& L ) { // 构造一个空的顺序表
L.elem = (ElemType*) malloc
(LIST_INIT_SIZE*sizeof
(ElemType));
if (!L.elem) exit(OVERFLOW);
L.length = 0;
L.listsize = LIST_INIT_SIZE
return OK;}
最后,对建立的顺序表设计插入、删除、查找等基本操作的算法如下:
Status ListInsert_Sq(SqList
&L, int i, ElemType e) {
// 在顺序表L的第 i
个元素之前插入新的元素e
if (i < 1 || i > L.length+1)
return ERROR;
if (L.length >= L.listsize)
{
newbase = (ElemType *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof (ElemType));
if (!newbase) exit(OVERFLOW);
L.elem = newbase;
L.listsize += LISTINCREMENT;
q = &(L.elem[i-1]);
for (p = &(L.elem[L.length-1]); p >= q; --p)
*(p+1) = *p; *q = e; ++L.length;
return OK;}
Status ListDelete_Sq (SqList
&L, int i, ElemType &e)
{ //删除算法
if ((i < 1) || (i > L.length))
return ERROR;
p = &(L.elem[i-1]);
e = *p;
q = L.elem+L.length-1;
for (++p; p <= q; ++p) *(p-1) = *p;
--L.length;
return OK;}
int locate_sq(SqList L ,elemtype x) //查找算法
{ for(i=0;i<L.length;i++)
If(L.elem[i]==x) return i+1;
return 0;
}
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
实验二 线性表的链式表示与实现
1.实验目的
(1) 掌握线性表的链接存储结构;
(2) 验证单链表及其基本操作的实现;
(3) 进一步掌握数据结构及算法的程序实现的基本方法。
2.实验内容
(1)
用头插法和尾插法建立含有若干个元素的带头结点的单链表;
(2)
对已经建立的单链表实现插入、删除、查找等基本操作。
3.实现算法见课本算法2.8至算法2.11
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
实验三栈及其应用(注意:如只有七次实验则三、四实验合成一次完成)
1.实验目的
(1) 掌握栈的顺序存储结构;
(2) 掌握栈的操作特性;
(3) 掌握基于顺序栈的基本操作的实现方法。
2.实验内容
(1)
建立一个空栈;
(2)
对已经建立的栈实现入栈、出栈、取栈顶元素等基本操作。
3.实现算法见课本
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
实验四 队列及其应用
1.实验目的
(1) 掌握队列的链式存储结构;
(2) 掌握队列的操作特性;
(3) 掌握链队列的基本操作的实现方法。
2.实验内容
(1)
建立一个空队列;
(2)
对已经建立的队列实现插入、删除等基本操作
3.实现算法见课本
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
实验五二叉树的应用
1.实验目的
(1) 掌握二叉树的逻辑结构;
v 是n(n>=0)个结点的有限集,其子树分为互不相交的两个集合,分别称为左子树和右子树,左子树和右子树也是二叉树。
(2)
掌握二叉树的二叉链表存储结构;
q 二叉链表
v 结点除包括元素自身的信息外,还包括指向其左、右子树的指针。即结点要包括数据域,左子树指针域和右子树指针域。
(3)
掌握基于二叉链表存储的二叉树的遍历操作的实现。
先序遍历,中序遍历,后序遍历
2.实验内容
(1)
建立一棵含有n个结点的二叉树;
(2)
前序(或中序、后序)遍历该二叉树;
(3)
求该树叶子结点个数。
3.实现算法见课本
1)建立二叉树算法
void CreateBiTree(BiTree &T){
// 按先序序列输入二叉树中结点的值(一个字符),空格表示空树,
// 构造二叉链表表示的二叉树T。
scanf(&ch) ;
if(ch == ‘ ’) T=NULL; //
建空树
else {
if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) eixt(OVERFLOW);
T->data = ch; // 生成根结点
CreateBiTree(T->Lchild); // 递归建(遍历)左子树
CreateBiTree(T->Rchild); // 递归建(遍历)右子树
} // else
return OK;
} // CreateBiTree
2)先序遍历二叉树
Status PreOrderTraverse(BiTree T,Status(*visit)(TElemType e)){
// 采用二叉链表存储结构,visit是对元素操作的应用函数,
// 先序遍历二叉树T的递归算法,对每个数据元素调用函数visit。
// 最简单的visit函数是输出元素的值。
if (T) {
visit(T->data);
PreOrderTraverse(T->lchild, visit);
PreOrderTraverse(T->rchild, visit);
}//if
}// PreOrderTraverse
3)
求该树叶子结点个数。
q 算法思想:对二叉树“遍历”一遍,并在遍历过程中对“叶子结点计数”
即可。为了在遍历的同时进行计数,在算法的参数中设
一个“计数器”。这个遍历的次序可以随意,即先序或中序或后序均可。
void CountLeaf (BiTree T, int& count){
// 先序遍历二叉树,以 count 返回二叉树中叶子结点的数目
if ( T ) {
if ((!T->Lchild) && (!T->Rchild)) count++;
CountLeaf( T->Lchild, count);
CountLeaf( T->Rchild, count);
}// if
}// CountLeaf
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
5. 扩展求二叉树的深度
实验六 图的遍历与应用
一.实验目的
(1) 掌握图的逻辑结构;
(2) 掌握图的邻接矩阵存储结构和邻接表存储结构;
(3) 掌握图的邻接矩阵存储结构和邻接表存储结构下遍历算法的实现。
二.实验内容
[问题描述]
对给定图,实现图的深度优先遍历和广度优先遍历。
[基本要求]
以邻接表或邻接矩阵为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列。
(1)建立无向图的邻接矩阵存储;
(2)对已经建立的无向图进行深度优先和广度优先遍历操作。
(3)建立有向图的邻接表存储;
(4)对已经建立的有向图进行深度优先和广度优先遍历操作。
三、实验前的准备工作
1、掌握图的相关概念。
2、掌握图的逻辑结构和存储结构。
图的数组(邻接矩阵)存储表示
#define INFINITY INT_MAX; // 最大值∞
#define MAX_VERTEX_NUM 20; // 最大顶点个数
typedef enum {DG,DN,UDG,UDN} GraphKind;// {有向图,有向网,无向图,无向网}
typedef struct ArcCell {
VRType adj; // VRType是顶点关系类型。对无权图,用1或0
// 表示相邻否;对带权图,则为权值类型。
InfoType *info; // 该弧相关信息的指针
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
VertexType vexs[MAX_VERTEX_NUM]; // 顶点信息
AdjMatrix arcs; // 邻接矩阵
int vexnum, arcnum; // 图的当前顶点数和弧(边)数
GraphKind kind; // 图的种类标志
} MGraph;
图的邻接表存储表示:
#define MAX_VERTEX_NUM 20;
typedef struct ArcNode {
int adjvex; // 该弧所指向的顶点的位置
struct ArcNode *nextarc; // 指向下一条弧的指针
InfoType *info; // 该弧相关信息的指针
} ArcNode;
typedef struct VNode {
VertexType data; // 顶点信息
ArcNode *firstarc; // 指向第一条依附该顶点的弧
} AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices; // 顶点数组
int vexnum, arcnum; // 图的当前顶点数和弧数
int kind; // 图的种类标志
} ALGraph;
3、掌握图的两种遍历算法的实现。
深度优先遍历算法
具体算法:
Boolen visited[MAX]; //访问标志数组
Status (* visitFunc)(int v); //函数变量
void DFSTraverse(Graph G, Status( * visit)(int v)){
// 对图G作深度优先遍历
visitFunc=visit; //使用全局变量visitFunc
,
//使DFS不必设函数指针参数
for (v=0; v<G.vexnum; ++v)
visited[v] = FALSE; //
访问标识数组初始化
for (v=0; v<G.vexnum; ++v)
if (!visited[v]) DFS(G, v); // 对尚未访问的
//顶点调用DFS
}
void DFS(Graph G, int v){
// 从第v个顶点出发递归地对图G进行深度优先搜索
visitFunc( v );
// 访问第 v
个顶点
visited[v] = TRUE;
// 设访问标志
for ( w=FirstAdjVex(G,v); w>=0;w=NextAdjVex(G,v,w))
if (!visited[w]) DFS(G, w); //
对v的尚未访问过的邻接
//顶点w递归调用DFS
} // DFS
广度优先遍历算法:
具体算法:
void BFSTraverse(Graph G, Status( * visit)(int v)){
// 对图G进行广度优先搜索遍历
for (v=0; v<G.vexnum; ++v) visited[v] = FALSE;
InitQueue(Q); //
设置空队列 Q
for ( v=0; v<G.vexnum; ++v )
if ( !visited[v]){
// v未被访问
visited[v] = TRUE; Visit (v); //
访问v
EnQueue(Q, v); // v
入队列
while (!QueueEmpty(Q)) {
DeQueue(Q, u); //
队头元素出队并置为 u
for ( w=FirstAdjVex(G,u); w>=0; w=NextAjdVex(G,u,w))
if (! visited[w] ) {
visited[w] = TRUE; Visit(w); //
访问第 w 个顶点
EnQueue(Q, w);
} // if
} // while
} // if
DestroyQueue(Q);
} // BFSTraverse
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
四、实验报告要求
1、实验报告要按照实验报告格式规范书写。
2、实验上要写出多批测试数据的运行结果。
3、结合运行结果,对程序进行分析。
实验七
查找技术
1.
实验目的
(1) 掌握顺序查找和折半查找算法的基本思想;
(2) 掌握顺序查找和折半查找算法的实现方法;
(3) 掌握顺序查找和折半查找算法的时间性能。
2.
实验内容
对给定的长度为n的数组,分别使用顺序查找、折半查找查找数组中与给定值k相等的元素。
3.
实现算法见课本
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。
实验八
内部排序
1.
实验目的
(1) 掌握直接插入排序、冒泡排序和简单选择排序的基本思想;
(2) 掌握直接插入排序、冒泡排序和简单选择排序的实现方法;
(3) 掌握快速排序的基本思想和实现方法。
2.
实验内容
对一组数据进行直接插入排序、冒泡排序、简单选择排序和快速排序。(升序)
3.
实现算法见课本
4.根据上面设计的算法,用C/C++语言实现,调试通过并输出正确的结果。