《 — 数据结构 —》
实验指导书
朱素英 编 写
适用专业: 计算机科学与技术
计算机网络工程
湖南人文科技学院计算机科学技术系
2008 年 8 月
前 言
《数据结构》课程是计算机科学与技术专业的一门必修的专业基础课。这门课程的主要特点是实践性很强,不仅要学习基本理论知识,更要注重上机实践,通过上机实践验证算法的正确性,掌握和巩固所学理论知识。通过对本课程中算法设计和上机实践的训练,培养学生的数据抽象能力和程序设计的能力,为后续课程,特别是软件课程打下坚实的知识基础。要求学生掌握各种常用数据结构的逻辑结构,存储结构及有关操作的算法。
通过本课程的学习,要求学生了解数据结构及其分类、数据结构与算法的密切关系; 熟悉各种基本数据结构及其操作,学会根据实际问题要求来选择数据结构; 掌握设计算法的步骤和算法分析方法; 掌握数据结构在排序和查找等常用算法中的应用。
为了使学生更好地理解和深刻地把握这些知识,并在此基础上,训练和培养了解数据结构及其分类、数据结构与算法的密切关系; 熟悉各种基本数据结构及其操作,学会根据实际问题要求来选择数据结构; 掌握设计算法的步骤和算法分析方法; 掌握数据结构在排序和查找等常用算法中的应用等方面的技能,设置的以下十二个的具体实验项目,这些实验项目中有验证性实验、综合性实验与设计性实验,在每一个具体实验中都有标明。各项实验主要了解、掌握的具体知识,在每个实验中都有说明。
本实验指导书对计算机科学与技术专业与网络工程专业均适应。
目录
实验一:顺序表的基本操作 1
实验二:单链表的基本操作 9
实验三:栈的基本操作 14
实验四:队列的基本操作 16
实验五:串的模式匹配 19
实验六:矩阵的基本运算 22
实验七:二叉树的基本操作 29
实验八:哈夫曼树与哈夫曼编码 34
实验九:图的最短路径算法 38
实验十:哈希表的基本操作 40
实验十一:各种排序算法 44
实验十二:银行模拟 48
实验一:顺序表的基本操作
实验学时:2
实验类型:验证
实验要求:选修
一、实验目的
1.掌握使用VC++进行控制台应用程序编写的基本方法
2.掌握顺序表的初始化、销毁、数据元素的插入和删除以及顺序表的输出等基本操作。
二、实验内容
顺序表的初始化、插入和删除
三、 程序清单
1、运行环境
Visual c++ 6.0的微机一台
2、程序清单
#include "stdio.h"
#include "stdlib.h"
# define OVERFLOW -2
# define OK 1
#define ERROR 0
typedef int ElemType;
typedef int Status;
# define List_init_size 100
# define Listincrement 10
typedef struct{
ElemType *elem;
int length;
int listsize;
}sqlist;
Status InitList(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 sqlistinput(sqlist &L,int n)
{int i=0;
if(n>L.listsize)return ERROR;
for(;i<n;i++)
{scanf("%d",&L.elem[i]);
}
L.length=n;
return OK;
}
Status ListEmpty(sqlist L)
{if (!L.length) return ERROR;
else return OK;
}
Status ListLength(sqlist L)
{ return L.length;
}
Status sqlistoutput(sqlist L)
{int i;
for(i=0;i<ListLength(L);i++)
printf("%4d",L.elem[i]);
printf("
");
return OK;}
Status GetElem(sqlist l,int i,ElemType &e)
{
if (i<1 || i>l.length+1) return ERROR;
e=l.elem[i-1];
return OK;
}
Status equal(ElemType e1,ElemType e2)
{if (e1==e2)
return OK;
else
return ERROR;
}
int LocateElem_sq(sqlist L,ElemType e,Status (*compare)(ElemType,ElemType))
{ int i=1;
ElemType *p;
p=L.elem;
while(i<=L.length &&!(*compare)(*p++,e)) ++i;
if (i<=L.length) return i;
else return 0;
}
Status PriorElem(sqlist L,ElemType cur_e,ElemType &pre_e)
{ int pos;
pos=LocateElem_sq(L,cur_e,equal);
if(pos==0) return ERROR;
else if(pos==1) return OVERFLOW;
else{
GetElem(L,pos-1,pre_e);
return OK;
}
}
Status NextElem(sqlist L,ElemType cur_e,ElemType &next_e)
{ int pos;
pos=LocateElem_sq(L,cur_e,equal);
if(pos==0) return ERROR;
else if(pos==L.length) return OVERFLOW;
else{
GetElem(L,pos+1,next_e);
return OK;
}
}
Status Listinsert_sq(sqlist &L,int i,ElemType e) {
ElemType *p,*q,*newbase;
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)
{
ElemType *p,*q;
if (i<1||i>l.length+1) 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;
}
void mergelist_sq(sqlist la,sqlist lb,sqlist &lc)
{ ElemType *pa,*pb,*pc,*pa_last,*pb_last;
pa=la.elem;
pb=lb.elem;
lc.listsize=lc.length=la.length+lb.length;
pc=lc.elem=(ElemType*)malloc(lc.listsize*sizeof(ElemType));
if (!lc.elem) exit(OVERFLOW);
pa_last=la.elem+la.length-1; pb_last=lb.elem+lb.length-1;
while ((pa<=pa_last)&& (pb<=pb_last))
if (*pa<=*pb) *pc++=*pa++; else *pc++=*pb++ ;
while(pa<=pa_last) *pc++=*pa++;
while(pb<=pb_last) *pc++=*pb++;
}
Status sortsqlist(sqlist &L)
{
int i,j,len;
ElemType t;
len=ListLength(L);
for(i=len-1;i>=1;i--)
for(j=0;j<i;j++)
{if (L.elem[j]>L.elem[j+1])
{t=L.elem[j];
L.elem[j]=L.elem[j+1] ;
L.elem[j+1]=t;
}
}
return OK;
}
void main()
{sqlist la,lb,lc;
int n,m,i,e,k,cur_e,pre_e,next_e;
InitList(la);InitList(lb);
printf("please input la's numbers:n(请输入线性表la的元素个数n)
");
scanf("%d",&n);
printf("please input la n numbers:( 请输入线性表la的n个元素)
");
sqlistinput(la,n);
sqlistoutput(la);
printf("
");
printf("请输入要插入的元素的位置和插入的值
");
scanf("%d%d",&i,&e);
Listinsert_sq(la,i,e);
sqlistoutput(la);
printf("请输入要删除的元素的位置
");
scanf("%d",&i);
Listdelete_sq(la,i,e);
printf("the dele data is %d
",e);
sqlistoutput(la);
printf("please input the get data's locate
");
scanf("%d",&i);
GetElem(la,i,e);
printf("the get data is %d
",e);
printf("please input the locateelem's data :cur_e
");
scanf("%d",&cur_e);
k=LocateElem_sq(la,cur_e,equal);
printf("the locate is %d
",k);
printf("please input the cur_e data
");
scanf("%d",&cur_e);
PriorElem(la,cur_e,pre_e);
printf("the pre_e is %d
",pre_e);
printf("please input the cur_e data
");
scanf("%d",&cur_e);
NextElem(la,cur_e,next_e);
printf("the next_e is %d
",next_e);
printf("please input lb's numbers:m
");
scanf("%d",&m);
printf("please input lb m numbers:
");
sqlistinput(lb,m);
printf("
");
sqlistoutput(lb);
sortsqlist(la);
printf("the sort list la is:
");
sqlistoutput(la);
sortsqlist(lb);
printf("the sort list lb is:
");
sqlistoutput(lb);
mergelist_sq(la,lb,lc);
printf("la and lb's mergelist is:
");
sqlistoutput(lc);
}
四、思考题
1.如何实现顺序表的逆置
2.每次删除操作时,都会使得大量的数据元素移动,删除多个数据元素时,就需多次移动数据元素。能否一次进行删除多个数据元素的操作,使得数据元素的移动只进行一次。
实验二:单链表的基本操作
实验学时:2
实验类型:验证
实验要求:必修
一、 实验目的
1.定义单链表的结点类型。
2.熟悉对单链表的一些基本操作和具体的函数定义。
3.通过单链表的定义掌握线性表的链式存储结构的特点。
4.掌握循环链表和双链表的定义和构造方法
二、实验内容
链表的创建、插入与删除操作
三、程序清单
1、运行环境
装有Visual c++6.0的微机一台
2、程序清单
#include "stdio.h"
#include"stdlib.h"
#define NULL 0
#define error 0
#define ok 1
#define overflow -2
#define infeasible -1
typedef int Status;
typedef int ElemType;
typedef struct LNode
{int data;
struct LNode *next;
}LNode,*LinkList;
Status GetElem_l(LinkList L, int i , ElemType &e)
{int j;
LinkList p ;
p=L->next; j=1;
while(p&&j<i)
{p=p->next; ++j;}
if(!p||j>i) return error;
e=p->data;
return ok;
}
void CreatList_L1(LinkList &L,int n)
{int i;
LinkList p;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
for(i=n;i>0;i--)
{ p=(LinkList)malloc(sizeof(LNode));
scanf("%d",&p->data);
p->next=L->next;
L->next=p;
}
}
void CreatList_L2(LinkList &L,int n )
{int i ;
LinkList p,q;
L=(LinkList )malloc(sizeof(LNode));
q=L;
for(i=0;i<n;i++)
{ p=(LinkList )malloc(sizeof(LNode));
scanf("%d",&p->data);
q->next=p;
q=p;
}
q->next=NULL;
}
void print(LinkList L)
{LinkList p;
p=L->next;
while(p)
{printf("%d ",p->data);
p=p->next;
}
}
int ListInsert(LinkList &L,int i,int e)
{LinkList p,s;
int j;
p=L;j=0;
while(p&&j<i-1)
{p=p->next; ++j;}
if(!p||j>i-1) return error;
s=(LinkList)malloc(sizeof(LNode));
s->data=e; s->next=p->next;
p->next=s;
return ok;
}
int ListDelete(LinkList &L,int i,int &e)
{LinkList p,q;
int j;
p=L; j=0;
while(p->next&&j<i-1)
{ p=p->next; ++j;}
if(!(p->next)||j>i-1) return error;
q=p->next;p->next=q->next;
e=q->data;free(q);
return ok;
}
Status sortlinklist(LinkList &L)
{LinkList p,q,r;
ElemType t;
p=L->next;
while(p->next!=NULL)
{q=L->next;
while(q->next!=NULL)
{r=q->next;
if(q->data>r->data)
{t=q->data; q->data=r->data; r->data=t; }
q=q->next;
}
p=p->next;
}
return ok ;
}
void mergelist_l(LinkList la, LinkList &lb, LinkList &lc)
{LinkList pa,pb,pc;
pa=la->next; pb=lb->next ;
lc=pc=la;
while(pa&&pb)
if(pa->data <=pb->data)
{pc->next=pa;pc=pa;pa=pa->next;}
else {pc->next=pb;pc=pb;pb=pb->next;}
pc->next=pa?pa:pb;
free(lb);
}
void main()
{LinkList L1,L2,L3;
int n,ins,del,i;
printf("please input fifo linklist's node number n:
");
scanf("%d",&n);
printf("please input the linklist %d nodes data
",n);
CreatList_L2(L2,n);
print(L2);
printf("
");
printf("please input lifo linklist's node number n:
");
scanf("%d",&n);
printf("please input the linklist %d nodes data
",n);
CreatList_L1(L1,n);
print(L1);
printf("
");
printf("please input the insert node's locate i and value e
");
scanf("%d%d",&i,&ins);
ListInsert(L1,i,ins);
print(L1);
printf("
");
printf("please input the delete node's locate i
");
scanf("%d",&i);
ListDelete(L1,i,del);
print(L1);
printf("
%d
",del);
sortlinklist(L1);
printf("
the L1 list's sort is:
");
print(L1);
printf("
the L2 list's sort is:
");
sortlinklist(L2);
print(L2);
printf("
the merge result is :
" );
mergelist_l(L1,L2,L3);
print(L3);
}
四、思考题
l.如果需要将新结点插入到第i个数据元素之后,算法将如何改动?
2. 双向链表和循环链表的定义和构造方法。
实验三:栈的基本操作
实验学时:2
实验类型:验证
实验要求:选修
一、实验目的
1.会定义顺序栈和链栈的结点类型。
2.掌握顺序栈的插入和删除结点在操作上的特点。
3.熟悉对顺序栈的一些基本操作和具体的函数定义。
二、实验内容
栈的初始化、进栈与出栈等基本操作
三、程序清单
1、运行环境
装有Visual 6.0的微机一台
2、程序清单
#define stackinitsize 20
#define stackincrement 8
#include <stdlib.h>
#include <stdio.h>
typedef struct{
int *base;
int *top;
int stacksize;
}sqstack;
int initstack(sqstack &s)
{s.base=(int * ) malloc(stackinitsize*sizeof(int));
s.top=s.base;
s.stacksize=stackinitsize;
return 1;
}
int push(sqstack &s,int e)
{
s.top)=e;
s.top++;
return 1;
}
int gettop(sqstack s)
{
return *(s.top-1);
}
int emptystack(sqstack s)
{if (s.top==s.base) return 1;
else return 0;
}
int pop(sqstack &s,int &e)
{ if (emptystack(s)) return 0;
--s.top;
*e=*s.top;
return 1;
}
Void main()
{
Sqstack s;
Int n,I,e;
initstack(s);
scanf(“%d”,&n);
for(i=1;i<=n;i++)
{scanf(“%d”,&e);
Push(s,e);
}
While(!emptystack(s))
{pop(s,e);
Printf(“%d ”,e);
}
}
四、思考题
如果两个栈共用一个存储空间,该如何解决?
实验四:队列的基本操作
实验学时:2
实验类型:验证
实验要求:选修
一、实验目的
1.会定义循环队列的结点类型。
2.循环队列的插入和删除结点在操作上的特点。
3.熟悉对循环队列的一些基本操作和具体的函数定义
二、实验内容
循环队列的插入与删除
三、程序清单
1、运行环境
装有Visual 6.0的微机一台
2、程序清单
# include "stdlib.h"
# include "stdio.h"
# include "time.h"
# define TURE 1
# define FALSE 0
# define OK 1
# define ERROR 0
# define OVERFLOW -2
# define maxqsize 100
typedef int status;
typedef int qelemtype;
typedef struct{
qelemtype *base;
int front;
int rear;
}sqqueue;
status initqueue(sqqueue &Q){
Q.base=(qelemtype*)malloc(maxqsize*sizeof(qelemtype));
if(!Q.base) return ERROR;
Q.front=Q.rear=0;
return OK;
}
int queuelength(sqqueue Q){
return (Q.rear-Q.front+maxqsize)%maxqsize;
}
status enqueue(sqqueue &Q,qelemtype e){
if((Q.rear+1)%maxqsize==Q.front) return ERROR;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%maxqsize;
return OK;
}
status dequeue(sqqueue &Q,qelemtype &e){
if(Q.front==Q.rear) return ERROR;
e=Q.base[Q.front];
Q.front=(Q.front+1)%maxqsize;
return OK;
}
void main()
{
int i,e;
sqqueue Q;
initqueue(Q);
printf("
");
for(i=1;i<=10;i++)
{
e=i;
enqueue(Q,e);
}
printf("the length of queue is :%d
",queuelength(Q));
for(i=1;i<=10;i++)
{
dequeue(Q,e);
printf(" %d",e);
}
}
四、思考题
1. 如果循环队列的下标不是从0开始,而是是从1开始,那么头指针加l的操作应如何修改?
2. 在循环队列中判断队空和队满的条件能否一样,为什么?
3. 用另一种不同与上面算法的方法解决“假上溢”问题。
实验五:串的模式匹配
实验学时:2
实验类型:验证
实验要求:选修
一、实验目的
1.会定义定长顺序串的存储结构。
2.掌握定长顺序串的基本运算。
3.了解KMP算法。
二、实验内容
串的模式匹配算法
三、程序清单
1、运行环境
2、程序清单
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <dos.h>
#define maxstrlen 255 //用可以在255以内定义最大串长
typedef unsigned char SString[maxstrlen+1];
int index(SString S,SString T,int pos) {
int i,j;
i=pos;j=1;
while(i<=S[0]&&j<=T[0]) {
if(S[i]==T[j]) {++i;++j;}
else
{i=i-j+2;j=1;}
}
if(j>T[0]) return i-T[0];
else
return 0;
}
void main()
{
SString S={17,'a','c','a','b','a','a','b','a','a','b','c','a','c','a','a','b','c'};
SString T={6,'a','b','a','a','b','c'};
printf("
it is :%d ",index(S,T,1));
}
#include <stdio.h>
#include <stdlib.h>
#define maxstrlen 255 //用可以在255以内定义最大串长
int next[7];
typedef unsigned char SString[maxstrlen+1];
void get_next(SString T) {
int i,j;
i=1; next[1]=0; j=0;
while(i<T[0]){
if(j==0||T[i]==T[j]) {++i; ++j; next[i]=j;}
else j=next[j];
}
printf("
next[j] is:");
for(i=1;i<=6;i++)
printf("%d",next[i]);
}
int index_kmp(SString S,SString T,int pos) {
int i,j;
i=pos;j=1;
while(i<=S[0]&&j<=T[0]) {
if(j==0||S[i]==T[j]) {++i;++j;}
else
j=next[j];
}
if(j>T[0]) return i-T[0];
else
return 0;
}
void main()
{
SString S={17,'a','c','a','b','a','a','b','a','a','b','c','a','c','a','a','b','c'};
SString T={6,'a','b','a','a','b','c'};
get_next(T);
printf("
it is :%d ",index_kmp(S,T,1));
}
四、思考题
1.如何使得在串插入和联接时不会上溢。
2.串的其它存储结构的实现。
实验六:矩阵的基本运算
实验学时:2
实验类型:设计
实验要求:选修
一、实验目的
1.了解多维数组的顺序存储结构及其地址计算方式
2.了解特殊矩阵和稀疏矩阵的概念。
3.掌握疏矩阵的压缩存储方式——三元组表。
4.掌握稀疏矩阵的两种转置运算算法。
二、实验内容
数组的稀疏矩阵的三元组存储表示与实现
三、程序清单
1、运行环境
2、程序清单
#define MAXSIZE 100 //假设非零元个数的最大值为100
#define ROW 7
#define COL 7
#define OK 1
#define FALSE 0
#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
int a[ROW][COL]={{0,12,9,0,0,0,0},
{0,0,0,0,0,0,0},
{-3,0,0,0,0,14,0},
{0,0,24,0,0,0,0},
{0,18,0,0,0,0,0},
{15,0,0,-7,0,0,0},
{0,0,0,0,0,0,-5}};
typedef int ElemType;
typedef int Status;
typedef struct{
int i,j;
ElemType e;
}Triple;
typedef union{
Triple data[MAXSIZE+1];
int mu,nu,tu;
}TSMatrix;
void InitTSMatrix(TSMatrix &T)
{ T.tu=0;
}
Status ChangeArrayToMS(int a[][COL],TSMatrix &T)
{ int i,j,k=0;
for(i=0;i<ROW;i++)
for(j=0;j<COL;j++)
if (a[i][j])
{++k;
T.data[k].i=i+1;T.data[k].j=j+1;T.data[k].e=a[i][j];
}
T.mu=ROW;T.nu=COL;T.tu=k;
return OK;
}
void PrintTSmatrix(TSMatrix T)
{
int k;
if(T.tu>0)
{ printf("
row col val
");
printf("------------------
");
for(k=1;k<=T.tu;k++)
printf("(%4d%5d%5d)
",T.data[k].i,T.data[k].j,T.data[k].e);
}
}
Status TransposeSMatrix(TSMatrix M, TSMatrix &T) {
int q,p,col;
T.mu=M.nu;T.nu=M.mu;T.tu =M.tu;
if(T.tu) {
q = 1;
for (col=1 ;col<=M.nu; ++col)
for (p=1; p<=M.tu; ++p)
if (M.data[p].j==col){
T.data[q].i=M.data[p].j ; T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e; ++q;}
}
return OK;
}
Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){
int t,col,p,q,num[COL+1],cpot[COL+1];
T.mu=M.nu;T.nu=M.mu;T.tu= M.tu;
if(T.tu) {
for (col = 1; col<= M.mu;++col) num[col] = 0;
for (t=1;t<=M.tu;++t) ++num[M.data[t].j];
cpot[ 1 ] = 1 ;
for (col = 2;col<= M.nu; ++col) cpot[col]=cpot[col-1] + num[col-1];
for (p=1; p<=M.tu;++p)
{ col=M.data[p].j;q=cpot[col];
T. data[q].i=M.data[p].j; T.data[q].j=M.data[p].i;
T. data[q].e=M.data[p].e; ++cpot[col];
}
}
return OK ;
}
Status AddTSMatrix(TSMatrix A,TSMatrix B,TSMatrix &C)
{
int p,q,k;
p=q=k=1;
if (A.mu!=B.mu||A.nu!=B.nu)
return FALSE;
if(A.tu==0&&B.tu==0) {C.tu=0;return OK;}
C.mu=A.mu;C.nu=A.nu;
while(p<=A.tu&&q<=B.tu)
{if ((A.data[p].i==B.data[q].i)&&(A.data[p].j==B.data[q].j))
{ if (A.data[p].e+B.data[q].e)
{ C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
C.data[k].e=A.data[q].e+B.data[q].e;
}
p++;q++;k++;
}
else if((A.data[p].i>B.data[q].i)||
((A.data[p].i==B.data[q].i)&&(A.data[p].j>B.data[q].j)))
{C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
C.data[k].e=B.data[q].e;q++;k++;}
else
{C.data[k].i=A.data[p].i;C.data[k].j=A.data[p].j;
C.data[k].e=A.data[p].e;p++;k++;}
}
while (p<=A.tu)
{C.data[k].i=A.data[p].i;C.data[k].j=A.data[p].j;
C.data[k].e=A.data[p].e;p++;k++;}
while (q<=B.tu)
{C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
C.data[k].e=B.data[q].e;q++;k++;}
C.tu=k-1;
return OK;
}
void main()
{ TSMatrix T,T1,T2;
InitTSMatrix(T);getch();
ChangeArrayToMS(a,T);
PrintTSmatrix(T);getch();
TransposeSMatrix(T,T1);
PrintTSmatrix(T1);getch();
FastTransposeSMatrix(T,T1);
PrintTSmatrix(T1);getch();
AddTSMatrix(T,T1,T2);
PrintTSmatrix(T2);
}
四、思考题
1.稀疏矩阵的十字链表又是如何实现的?
实验七:二叉树的基本操作
实验学时:2
实验类型:设计
实验要求:必修
一、实验目的
1.熟悉二叉树结点的结构和对二叉树的基本操作。
2.掌握对二叉树每一种操作的具体实现。
3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
二、实验内容
二叉树的创建及各种周游
三、程序清单
1、运行环境
2、程序清单
#include "alloc.h"
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#define stackinitsize 100
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int TElemType ;
typedef int Status;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTnode,*SElemType,*BiTree;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}sqstack;
Status CreateBitree(BiTree &T);
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
Status InorderTraverse(BiTree T,Status(*Visit)(TElemType e));
Status PostorderTraverse(BiTree T,Status(*Visit)(TElemType e));
Status LevelIOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
sqstack *InitStack()
{sqstack *s;
s->base=(SElemType*)malloc(100*sizeof(SElemType));
if(!s->base) return NULL;
s->top=s->base;
s->stacksize=100;
return s;
}
int StackEmpty(sqstack *s)
{return(s->top==s->base);
}
void Pop(sqstack *s,SElemType &e)
{
e=*--s->top;
}
Status GetTop(sqstack *s,SElemType &e)
{
if(s->top==s->base) return ERROR;
e=*(s->top-1);
return OK;
}
void Push(sqstack *s,SElemType e)
{SElemType t;
*s->top++=e;
}
Status CreateBiTree(BiTree &T){
char ch;
ch=getche();
if(ch==' ') T=NULL;
else{
if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) return(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
{
if(T){
if (Visit(T->data))
if (PreOrderTraverse(T->lchild,Visit))
if (PreOrderTraverse(T->rchild,Visit)) return OK;
return ERROR;
}else return OK;
}
Status InOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
{
if(T){
if (InOrderTraverse(T->lchild,Visit))
if (Visit(T->data))
if (InOrderTraverse(T->rchild,Visit)) return OK;
return ERROR;
}else return OK;
}
Status PostOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
{
if(T){
if (PostOrderTraverse(T->lchild,Visit))
if (PostOrderTraverse(T->rchild,Visit))
if (Visit(T->data)) return OK;
return ERROR;
}else return OK;
}
Status PrintElement(TElemType e)
{
printf("%c",e);
return OK;
}
Status InorderTraverseNoRecursion1(BiTree T,Status(*Visit)(TElemType e))
{sqstack *s;
BiTree p;
s=InitStack();p=T;
while(p||!StackEmpty(s))
{
if(p){ Push(s,p);p=p->lchild;}
else{
Pop(s,p);if(!Visit(p->data)) return ERROR;
p=p->rchild;
}
}
return OK;
}
Status InorderTraverseNoRecursion2(BiTree T,Status(*Visit)(TElemType e))
{sqstack *s;
BiTree p;
s=InitStack();Push(s,T);
while(!StackEmpty(s))
{
while(GetTop(s,p)&&p) Push(s,p->lchild);
Pop(s,p);
if(!StackEmpty(s)) {
Pop(s,p);if(!Visit(p->data)) return ERROR;
Push(s,p->rchild);
}
}
return OK;
}
void main()
{
BiTree t;
printf("
请按先序遍历输入二叉树(当左右子树为空时用空格输入)
");
CreateBiTree(t);
printf("
该二叉树的先序遍历为:
");
PreOrderTraverse(t,PrintElement);
printf("
该二叉树的中序遍历为:
");
InOrderTraverse(t,PrintElement);
printf("
该二叉树的后序遍历为:
");
PostOrderTraverse(t,PrintElement);
printf("
该二叉树的中序遍历为:(用非递归调用1)
");
InorderTraverseNoRecursion1(t,PrintElement);
printf("
该二叉树的中序遍历为:(用非递归调用2)
");
InorderTraverseNoRecursion2(t,PrintElement);
}
四、思考题
1.如何实现二叉树的层次遍历?
2. 如何实现二叉树的先序遍历、中序遍历和后序遍历的非递归算法。
实验八:哈夫曼树与哈夫曼编码
实验学时:2
实验类型:设计
实验要求:选修
一、实验目的
1.了解创建哈夫曼树的基本方法
2.掌握通过赫夫曼树进行赫夫曼编码的基本原理和方法。
二、实验内容
哈夫曼树与哈夫曼编码
三、程序清单
1、运行环境
2、程序清单
#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
#include "string.h"
#define ERROR 0;
#define OK 1;
typedef int Status ;
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
Status Select(HuffmanTree HT,int n,int &s1,int &s2) {
unsigned int temp=9999;
int i;
s1=0;s2=0;
for(i=1;i<=n;i++)
if((HT[i].weight<temp)&&(HT[i].parent==0))
{
s1=i;temp=HT[i].weight;
}
temp=9999;
for(i=1;i<=n;i++)
if((HT[i].weight<temp)&&(HT[i].parent==0)&&(i!=s1))
{
s2=i;temp=HT[i].weight;
}
if((s1==0)&&(s2==0)) return ERROR;
return OK;
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w[],int n)
{
HuffmanTree p;
char *cd;
int s1,s2,i,c,m,start,f;
if(n<1) return ;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
p=HT;p++;
for(i=1;i<=n;++i)
{
p->weight=w[i-1];
p->parent=0;
p->lchild=0;
p->rchild=0;
p++;
}
for(;i<=m;++i,++p)
{
p->weight=0;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(i=n+1;i<=m;++i)
{ Select(HT,i-1,s1,s2);
HT[s1].parent=i;HT[s2].parent=i;
HT[i].lchild=s1;HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
printf("
the huffmantree is:
");
printf(" NO [weight parent lchild rchild]
");
printf(" --------------------------------
");
for(i=1;i<=m;i++)
printf("%6d [%6d,%6d,%6d, %6d ]
",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]=' ';
for(i=1;i<=n;++i)
{ start=n-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if(HT[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
void main()
{
HuffmanTree HT;
int n,i,w[20];
HuffmanCode HC;
printf("please intput n=
");
scanf("%d",&n);
printf("please input w[%d]:
",n);
for(i=0;i<n;i++)
scanf("%d",&w[i]);
HuffmanCoding(HT,HC,w,n);
getch();
printf("
the HuffmanCoding is:
");
for(i=1;i<=n;i++)
printf("%s
",HC[i]);
}
实验九:图的最短路径算法
实验学时:2
实验类型:验证
实验要求:选修
一、实验目的
1.了解无向图的邻接表的存储表示
2.掌握通过无向图的邻接表进行无向图的深度优先搜索的基本原理和方法
二、实验内容
图的dijkstra算法
三、程序清单
1、运行环境
2、程序清单
#define max 1000
#define n 6
typedef int Graph[n][n];
typedef int vertex;
void shortp(Graph G,vertex v,int dist[n])
{
int i,wm,u,num=1,S[n];
for(i=0;i<n;i++)
{
dist[i]=G[v][i];
S[i]=0;
}
S[v]=1;
do{
wm=max;
u=v;
for(i=0;i<n;i++)
if(S[i]==0)
if(dist[i]<wm)
{
u=i;
wm=dist[i];
}
S[u]=1;
for(i=0;i<n;i++)
if(S[i]==0)
if(dist[u]+G[u][i]<dist[i])
dist[i]=dist[u]+G[u][i];
num++;
}while(num!=n-1);
}
main()
{
Graph G;
vertex v=0;
int dist[n],i,j;
printf("please input weight of Graph:
");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&G[i][j]);
shortp(G,v,dist);
for(i=0;i<n;i++)
printf("the shortest path of v[%d]->v[%d] is:%d
",v,i,dist[i]);
}
实验十:哈希表的基本操作
实验学时:2
实验类型:设计
实验要求:选修
一、实验目的
1.熟悉有关哈希表的基本概念。
2.熟悉构造哈希表的方法。
3.掌握处理哈希冲突的开放定址法。
二、实验内容
哈希表的动态生成与查找
三、程序清单
int hashsize[]={13,19,29,37};
C++;
if(c<m)
collision(p,c);/*求得下一探查地址p*/
else
return UNSUCCESS;/*查找不成功(H.elem[p].key==NULLKEY)*/
}
If EQ(K,H.elem[*p].key)
return SUCCESS;
return low;
}
void quicksort(sqlist a,int n,int low,int high)
{
int p,i;
if(low<high)
{
p=partion(a,n,low,high);
quicksort(a,n,low,p-1);
quicksort(a,n,p+1,high);
}
}
main()
{
int i,n=10;
char ch;
sqlist a;
for(i=1;i<=10;i++)
a[i]=11-i;
printf("
");
printf(" ┌─────────────┐
");
printf(" │ 1---插入排序 │
");
printf(" │ 2---希尔排序 │
");
printf(" │ 3---冒泡排序 │
");
printf(" │ 4---选择排序 │
");
printf(" │ 5---快速排序 │
");
printf(" │ 请选择(1--5) │
");
printf(" └─────────────┘
");
ch=getch();
if(ch=='1') {printf("插入排序的结果是:
");insertsort(a,n);}
else if(ch=='2'){printf("希尔排序的结果是:
");shellsort(a,n);}
else if(ch=='3'){printf("冒泡排序的结果是:
");bubblesort(a,n);}
else if(ch=='4'){printf("选择排序的结果是:
");selectsort(a,n);}
else if(ch=='5'){printf("快速排序的结果是:
");quicksort(a,n,1,n);}
else printf("对不起,你选择的参数不对!");
for(i=1;i<=10;i++)
printf("%5d",a[i]);
}
四、思考题
1.将上面几种排序算法进行比较
实验十二:银行模拟
实验学时:2
实验类型:综合
实验要求:选修
一、实验目的
掌握利用动态链表进行队列的动态事件的模拟
二、实验内容
银行模拟
三、程序清单
程序清单
# define CLOSTIME 480 /***银行下班时间(以分钟为单位)****/
# define ERROR 0
# define NULL 0
# define OVERFLOW -2
# define MAX_INTERTIME 10 /***距下一客户到达的最大时间*****/
# define MAX_DURTIME 15 /***处理单个客户业务的最大时间***/
# include "stdio.h "
# include "alloc.h"
# include "stdlib.h"
# include "conio.h"
typedef struct {
int occurtime;
int ntype ;
} event ,elemtype;
typedef struct linklist {
elemtype data ;
struct linklist *next ;
} linklist;
typedef struct {
linklist * head;
int len ;
} eventlist;
typedef struct {
int arrivaltime ;
int duration ;
} qelemtype;
typedef struct qnode{
qelemtype data;
struct qnode * next;
} qnode;
typedef struct {
qnode *front;
qnode *rear ;
int len ;
} linkqueue;
eventlist *ev;
event en;
linkqueue * q[5];
qelemtype customer;
int totaltime;
int customernum;
int cmp(event en,event b)
{
if (en.occurtime>=(b.occurtime)) return 1;
else return 0;
}
double random0_1()
{
static long seed=3;
long a=16807;
long m=2147483647;
long q=127773;
long r=2836;
seed=a*(seed%q)-r*(seed/q) ;
if(seed<0) seed+=m;
return (double)seed/(double)m;
}
void random2(int *durtime,int *intertime)
{
*durtime=(int)(1+MAX_DURTIME*random0_1()) ;
*intertime=(int)(MAX_INTERTIME*random0_1()) ;
}
eventlist * initlist ()
{
eventlist *evp;
evp=(eventlist*)malloc(sizeof(eventlist));
if(!evp)exit(OVERFLOW);
evp->head=NULL;
evp->len=0;
return (evp);
}
int emptyeventlist (eventlist * ev)
{
return(ev->len);
}
linklist * delfirst(eventlist * ev)
{
linklist *p;
p=ev->head;
ev->head=p->next;
ev->len--;
return (p) ;
}
event getcurelem(linklist *p)
{
return(p->data);
}
void orderinsert(eventlist* ev,event en)
{
event en_temp;
linklist* s ,*p,*q;
s=(linklist*)malloc(sizeof(linklist));
if(!s)exit (OVERFLOW);
else {
s->data=en;
s->next=NULL;
}
if(ev->head==NULL||(en.occurtime<ev->head->data.occurtime))
{ s->next=ev->head;
ev->head=s;
}
else
{
q=ev->head;
p=q->next ;
en_temp=getcurelem(p);
while((p!=NULL)&& en.occurtime>en_temp.occurtime)
{
q=p;
p=p->next;
en_temp=getcurelem(p);
}
s->next =p;
q->next=s;
}
ev->len++;
}
linkqueue * initqueue()
{
linkqueue * q;
q=(linkqueue*)malloc(sizeof(linkqueue));
if(!q)exit(OVERFLOW);
q->front=q->rear=(qnode*)malloc(sizeof(qnode));
if(!q->front)exit(OVERFLOW);
q->front->next=NULL;
q->len=0;
return(q) ;
}
void enqueue(linkqueue*q,qelemtype e)
{
qnode *p;
p=(qnode*)malloc(sizeof(qnode));
if(!p)exit(OVERFLOW);
else p->data=e;
p->next=NULL;
q->rear->next=p;
q->rear=p;
q->len++;
}
int queueempty(linkqueue*q)
{
return(q->len);
}
int queuelength(linkqueue*q)
{
return(q->len);
}
qelemtype delqueue(linkqueue *q)
{
qelemtype customer;
qnode *p;
if(q->front==q->rear)exit(ERROR);
p=q->front->next;
customer=p->data;
q->front->next=p->next;
if(q->rear==p)q->rear=q->front;
free(p);
q->len--;
return(customer);
}
qelemtype gethead_q(linkqueue*q)
{
qelemtype customer;
qnode *p;
if(!queueempty(q))exit(ERROR);
p=q->front->next;
customer=p->data;
return(customer);
}
int minnum(linkqueue*q[])
{
int min1,min2;
min1=queuelength(q[1])<=queuelength(q[2])? 1 : 2 ;
min2=queuelength(q[3])<=queuelength(q[4])? 3 : 4 ;
return queuelength(q[min1])<=queuelength(q[min2]) ? min1 :min2 ;
}
void openforday()
{
int i;
totaltime=0; customernum=0;
ev=initlist();
en.occurtime=0; en.ntype=0;
orderinsert(ev,en) ;
for(i=1;i<5;i++)
q[i]=initqueue();
}
void customerarrived()
{
event en_temp;
qelemtype e_temp;
int i,t,durtime,intertime;
customernum++;
random2(&durtime,&intertime);
t=en.occurtime+intertime;
en_temp.occurtime=t;
en_temp.ntype=0;
if(t<CLOSTIME)
orderinsert(ev,en_temp);
i=minnum(q);
e_temp.arrivaltime=en.occurtime;
e_temp.duration=durtime ;
enqueue(q[i],e_temp);
if(queuelength(q[i])==1)
{
en_temp.occurtime=en.occurtime+durtime;
en_temp.ntype=i;
orderinsert(ev,en_temp);
}
}
void customerdeparture()
{
event en_temp;
int i=en.ntype;
customer=delqueue(q[i]);
totaltime+=en.occurtime-customer.arrivaltime;
if(queueempty(q[i]))
{ customer=gethead_q(q[i]);
en_temp.occurtime=en.occurtime+customer.duration;
en_temp.ntype=i;
orderinsert(ev,en_temp);
}
}
void bank_simulation()
{
linklist *p;
openforday();
while(emptyeventlist(ev))
{
p=delfirst(ev);
en=getcurelem(p);
if(en.ntype==0)
customerarrived();
else customerdeparture();
}
printf("totaltime=%d customernum=%d
",totaltime,customernum);
printf("
the average time is %f
",(float)totaltime/(float)customernum);
}
void main()
{
bank_simulation();
}