队列
1.实验目标
熟练掌握队列的顺序存储结构和链式存储结构。
熟练掌握队列的有关算法设计,并在循环顺序队列和链队列上实现。
根据具体给定的需求,合理设计并实现相关结构和算法。
2.实验内容和要求
循环顺序队列的实验要求
循环顺序队列结构和运算定义,算法的实现以库文件方式实现,不得在测试主程序中直接实现;
实验程序有较好可读性,各运算和变量的命名直观易懂,符合软件工程要求;
程序有适当的注释。
链队列实验要求
本次实验中的链队列结构指不带头结点的单链表;
链队列结构和运算定义,算法的实现以库文件方式实现,不得在测试主程序中直接实现;
实验程序有较好可读性,各运算和变量的命名直观易懂,符合软件工程要求;
程序有适当的注释。
循环顺序队列实验任务
<1>初始化一个队列。
<2>判断是否队空。
<3>判断是否队满。
设队列最大长度:MaxLen=100
第一组数据:入队n个元素,判断队满
第二组数据:用循环方式将1到99,99个元素入队,判队满
<4>入队
第一组数据:4,7,8,12,20,50
第二组数据:a,b,c,d,f,g
<5>出队
<6>取队头元素
<7>求当前队列中元素个数
<8>编写算法实现
①初始化空循环队列;
②当键盘输入奇数时,此奇数入队;
③当键盘输入偶数时,队头出队;
④当键盘输入0时,算法退出;
⑤每当键盘输入后,输出当前队列中的所有元素。
链队列实验任务
<1>初始化一个队列。
<2>判断是否队空。
<3>判断是否队满。
设队列最大长度:MaxLen=100
第一组数据:入队n个元素,判断队满
第二组数据:用循环方式将1到99,99个元素入队,判队满
<4>入队
第一组数据:4,7,8,12,20,50
第二组数据:a,b,c,d,f,g
<5>出队
<6>取队头元素
<7>求当前队列中元素个数
<8>编写算法实现
①初始化空循环队列;
②当键盘输入奇数时,此奇数入队;
③当键盘输入偶数时,队头出队;
④当键盘输入0时,算法退出;
⑤每当键盘输入后,输出当前队列中的所有元素。
3.数据结构设计
#ifndef QUEUELIST_H_INCLUDED
#define QUEUELIST_H_INCLUDED
#include<stdio.h>
#include<stdlib.h>
#define maxlen 100
typedef struct squeue
{
int data[maxlen];
int lfront;
int lrear;
}seqqueue;
typedef struct cqueue
{
char data[maxlen];
int lfront;
int lrear;
}seqcqueue;
typedef struct lnode
{
int data;
struct lnode *next;
}node;
typedef struct
{
node *sfront;
node *srear;
}linkqueue;
typedef struct lcnode
{
char data;
struct lcnode *next;
}cnode;
typedef struct
{
cnode *cfront;
cnode *crear;
}linkcqueue;
void initialqueue(seqqueue q);
int queueempty(seqqueue q);
int queuefull(seqqueue q);
void enqueue(seqqueue q,int x);
void outqueue(seqqueue q);
void queuefront(seqqueue q,int x);
void queueall(seqqueue q);
void ssqueue(seqqueue q);
void encqueue(seqcqueue q,char x);
void initqueue(linkqueue q);
int queuelempty(linkqueue q);
int queuelfull(linkqueue q);
void enlqueue(linkqueue q,int x);
void outlqueue(linkqueue q);
void queuelfront(linkqueue q,int x);
void queuelall(linkqueue q);
void sslqueue(linkqueue q);
void enclqueue(linkcqueue q,char a);
seqqueue creatqueue(void)
{
seqqueue l;
int x;
l.lfront = 0;
l.lrear = 0;
printf("向队列中输入元素。(输入9999停止)\n");
scanf("%d",&x);
while(x!=9999)
{
l.lrear = ((l.lrear+1)%maxlen);
l.data[l.lrear] = x;
scanf("%d",&x);
}
return l;
}
seqcqueue creatcqueue(void)
{
seqcqueue l;
char x;
l.lfront = 0;
l.lrear = 0;
printf("向队列中输入元素。(输入0停止)\n");
scanf("%s",&x);
while(x!='0')
{
l.lrear = ((l.lrear+1)%maxlen);
l.data[l.lrear] = x;
scanf("%s",&x);
}
return l;
}
linkqueue creatlqueue(void)
{
linkqueue l;
int x;
node *p,*r;
l.sfront = (node *)malloc(sizeof(node));
l.srear = l.sfront;
l.sfront->next = NULL;
r = l.sfront;
printf("向队列中输入元素。(输入9999停止)\n");
scanf("%d",&x);
while(x!=9999)
{
p = (node *)malloc(sizeof(node));
p->data = x;
p->next = NULL;
l.srear = p;
r->next = p;
r = p;
scanf("%d",&x);
}
return l;
}
linkcqueue creatclqueue(void)
{
linkcqueue l;
char x;
cnode *p;
l.cfront = (cnode *)malloc(sizeof(cnode));
l.crear = l.cfront;
l.cfront->next = NULL;
printf("向队列中输入元素。(输入0停止)\n");
scanf("%c",&x);
while(x!='0')
{
p = (cnode *)malloc(sizeof(cnode));
p->data = x;
p->next = NULL;
l.crear->next = p;
l.crear = p;
scanf("%c",&x);
}
return l;
}
void menu(void)
{
int m;
loop:
printf("循环顺序队列实验任务:\n");
printf("<1>初始化一个队列。\n");
printf("<2>判断是否队空。\n");
printf("<3>判断是否队满。\n");
printf("<4>入队。(数字)\n");
printf("<5>入队。(字母)\n");
printf("<6>出队。\n");
printf("<7>取队头元素。\n");
printf("<8>求当前队列中元素个数。\n");
printf("<9>编写算法实现功能。\n");
printf("\n");
printf("链队列实验任务:\n");
printf("<10>初始化一个队列。\n");
printf("<11>判断是否队空。\n");
printf("<12>判断是否队满。\n");
printf("<13>入队。(数字)\n");
printf("<14>入队。(字母)\n");
printf("<15>出队。\n");
printf("<16>取队头元素。\n");
printf("<17>求当前队列中元素个数。\n");
printf("<18>编写算法实现功能。\n");
printf("\n");
printf("<19>清屏。\n");
printf("<20>退出。\n");
printf("\n");
scanf("%d",&m);
printf("\n");
switch(m)
{
case 1:
{
seqqueue q;
q = creatqueue();
initialqueue(q);
goto loop;
}
case 2:
{
seqqueue q;
q = creatqueue();
queueempty(q);
goto loop;
}
case 3:
{
seqqueue q;
q = creatqueue();
queuefull(q);
goto loop;
}
case 4:
{
seqqueue q;
int x;
q = creatqueue();
printf("输入入队元素。\n");
scanf("%d",&x);
enqueue(q,x);
goto loop;
}
case 5:
{
seqcqueue q;
char x;
q = creatcqueue();
printf("输入入队元素。\n");
scanf("%s",&x);
encqueue(q,x);
goto loop;
}
case 6:
{
seqqueue q;
q = creatqueue();
outqueue(q);
goto loop;
}
case 7:
{
seqqueue q;
int x;
q = creatqueue();
queuefront(q,x);
goto loop;
}
case 8:
{
seqqueue q;
q = creatqueue();
queueall(q);
goto loop;
}
case 9:
{
seqqueue q;
q = creatqueue();
ssqueue(q);
goto loop;
}
case 10:
{
linkqueue l;
l = creatlqueue();
initqueue(l);
goto loop;
}
case 11:
{
linkqueue l;
l = creatlqueue();
queuelempty(l);
goto loop;
}
case 12:
{
linkqueue l;
l = creatlqueue();
queuelfull(l);
goto loop;
}
case 13:
{
linkqueue l;
int x;
l = creatlqueue();
printf("输入入队元素。\n");
scanf("%d",&x);
enlqueue(l,x);
goto loop;
}
case 14:
{
linkcqueue l;
char x;
l = creatclqueue();
printf("输入入队元素。\n");
getchar();
scanf("%c",&x);
enclqueue(l,x);
goto loop;
}
case 15:
{
linkqueue l;
l = creatlqueue();
outlqueue(l);
goto loop;
}
case 16:
{
linkqueue l;
int x;
l = creatlqueue();
queuelfront(l,x);
goto loop;
}
case 17:
{
linkqueue l;
l = creatlqueue();
queuelall(l);
goto loop;
}
case 18:
{
linkqueue l;
l = creatlqueue();
sslqueue(l);
goto loop;
}
case 19:
{
system("cls");
goto loop;
}
case 20:
{
goto mmo;
}
default:
{
printf("输入错误。\n");
system("pause");
goto loop;
}
}
mmo:system("cls");
}
void initialqueue(seqqueue q) //<1>初始化一个队列。
{
q.lfront = 0;
q.lrear = 0;
printf("初始化完成。\n");
system("pause");
}
int queueempty(seqqueue q) //<2>判断是否队空。
{
if(q.lfront==q.lrear)
{
printf("队列为空。\n");
system("pause");
return 1;
}
else
{
printf("队列不为空。\n");
system("pause");
return 0;
}
}
int queuefull(seqqueue q) //<3>判断是否队满。
{
if(((q.lrear+1)%maxlen)==q.lfront)
{
printf("队列为满。\n");
system("pause");
return 1;
}
else
{
printf("队列未满。\n");
system("pause");
return 0;
}
}
void enqueue(seqqueue q,int x) //<4>入队
{
int i;
if(((q.lrear+1)%maxlen)==q.lfront)
{
printf("队列已满。\n");
system("pause");
}
else
{
q.lrear = ((q.lrear+1)%maxlen);
q.data[q.lrear] = x;
for(i=q.lfront+1;i<=q.lrear;i=i+1)
{
printf("%d\t",q.data[i]);
}
printf("\n");
system("pause");
}
}
void encqueue(seqcqueue q,char x) //<4>入队
{
int i;
if(((q.lrear+1)%maxlen)==q.lfront)
{
printf("队列已满。\n");
system("pause");
}
else
{
q.lrear = ((q.lrear+1)%maxlen);
q.data[q.lrear] = x;
for(i=q.lfront+1;i<=q.lrear;i=i+1)
{
printf("%c\t",q.data[i]);
}
printf("\n");
system("pause");
}
}
void outqueue(seqqueue q) //<5>出队
{
int i;
if(((q.lrear+1)%maxlen)==q.lfront)
{
printf("队列为空。\n");
system("pause");
}
else
{
q.lfront = (q.lfront+1)%maxlen;
for(i=q.lfront+1;i<=q.lrear;i=i+1)
{
printf("%d\t",q.data[i]);
}
printf("\n");
system("pause");
}
}
void queuefront(seqqueue q,int x) //<6>取队头元素
{
if(q.lfront==q.lrear)
{
printf("队列为空。\n");
system("pause");
}
else
{
x = q.data[(q.lfront+1)%maxlen];
printf("队头元素为:%d\n",x);
system("pause");
}
}
void queueall(seqqueue q) //<7>求当前队列中元素个数
{
int i,x;
x = q.lfront;
for(i=0;x<q.lrear;x=x+1)
{
i = i+1;
}
printf("队列中的元素个数为:%d\n",i);
system("pause");
}
void ssqueue(seqqueue q) //<8>编写算法实现
{
int i=0,x,j,k;
q.lfront = 0;
q.lrear = 0;
printf("向队列输入元素。(输入0后退出)\n");
scanf("%d",&x);
while(x!=0)
{
if(x%2==0)
{
if(i>0)
{
q.lfront = (q.lfront+1)%maxlen;
i = i-1;
}
else
{
printf("当前队列为空。");
}
}
else if(x%2!=0)
{
q.lrear = (q.lrear+1)%maxlen;
q.data[q.lrear] = x;
i = i+1;
}
k = q.lfront+1;
for(j=0;j<i;j=j+1)
{
printf("%d\t",q.data[k]);
k = k+1;
}
printf("\n\n");
scanf("%d",&x);
}
}
void initqueue(linkqueue q) //<1>初始化一个队列。
{
node *p,*s;
p = q.sfront->next;
s = p->next;
q.sfront->next = NULL;
while(p!=q.srear)
{
free(p);
p = s;
s = s->next;
}
q.srear = q.sfront;
printf("初始化完成。\n");
system("pause");
}
int queuelempty(linkqueue q) //<2>判断是否队空。
{
if(q.srear==q.sfront)
{
printf("队列为空。\n");
system("pause");
return 1;
}
else
{
printf("队列不为空。\n");
system("pause");
return 0;
}
}
int queuelfull(linkqueue q) //<3>判断是否队满。
{
int i=0;
node *s;
s = q.sfront->next;
while(s!=NULL)
{
i = i+1;
s = s->next;
}
if(i==100)
{
printf("队列已满。\n");
system("pause");
return 1;
}
else
{
printf("队列未满。\n");
system("pause");
return 0;
}
}
void enlqueue(linkqueue q,int x) //<4>入队
{
node *p;
p = (node *)malloc(sizeof(node));
p->data = x;
p->next = NULL;
q.srear->next = p;
q.srear = p;
p = q.sfront->next;
while(p!=NULL)
{
printf("%d\t",p->data);
p = p->next;
}
printf("\n");
system("pause");
}
void enclqueue(linkcqueue q,char a)
{
cnode *p,*u;
p = (cnode *)malloc(sizeof(cnode));
p->data = a;
p->next = NULL;
q.crear->next = p;
q.crear = p;
u = q.cfront->next;
while(u!=NULL)
{
printf("%c",u->data);
u = u->next;
}
printf("\n");
system("pause");
}
void outlqueue(linkqueue q) //<5>出队
{
node *u,*p;
int x;
if(q.srear==q.sfront)
{
printf("队列为空。\n");
system("pause");
}
else
{
x = q.sfront->next->data;
u = q.sfront->next;
q.sfront->next = u->next;
free(u);
p = q.sfront->next;
while(p!=NULL)
{
printf("%d\t",p->data);
p = p->next;
}
printf("\n");
system("pause");
}
}
void queuelfront(linkqueue q,int x) //<6>取队头元素
{
if(q.srear==q.sfront)
{
printf("队列为空。\n");
system("pause");
}
else
{
x = q.sfront->next->data;
printf("队头元素为:%d\n",x);
system("pause");
}
}
void queuelall(linkqueue q) //<7>求当前队列中元素个数
{
node *p;
int i=0;
p = q.sfront->next;
while(p!=NULL)
{
i = i+1;
p = p->next;
}
printf("当前队列元素个数为:%d\n",i);
system("pause");
}
void sslqueue(linkqueue q) //<8>编写算法实现
{
node *p,*s,*k,*u;
int x;
q.srear = q.sfront;
q.sfront->next = NULL;
printf("向队列输入元素。(输入0后退出)\n");
scanf("%d",&x);
s = q.sfront;
while(x!=0)
{
if(x%2!=0)
{
p = (node *)malloc(sizeof(node));
p->data = x;
p->next = NULL;
s->next = p;
s = p;
}
else if(x%2==0)
{
if(q.sfront->next==NULL)
{
printf("队列为空。\n");
}
else
{
u = q.sfront->next;
q.sfront->next = u->next;
free(u);
}
}
k = q.sfront->next;
while(k!=NULL)
{
printf("%d\t",k->data);
k = k->next;
}
printf("\n\n");
scanf("%d",&x);
}
}
#endif // QUEUELIST_H_INCLUDED
#include"Queuelist.h"
int main(void)
{
menu();
}
二叉树
1.实验目标
掌握二叉树的动态链表存储结构及表示。
掌握二叉树的三种遍历算法(递归和非递归两类)。
运用二叉树三种遍历的方法求解有关问题。
2.实验内容和要求
实验要求
结构定义和算法实现放入库文件,如“BiTree.h”中;
二叉树的测试数据用文本文件方式给出,例如测试数据名为bt151.btr的二叉树,其具体结构形式参见二叉树列表中的标有bt151.btr的二叉树图形。
实验任务
<1>打印出二叉树的三种遍历序。
实验测试数据基本要求:
第一组数据: bt151.btr
第二组数据: bt21.btr
<2>设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数。
实验测试数据基本要求:
第一组数据: bt151.btr
第二组数据: bt21.btr
<3>求二叉树的高度。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<4>求二叉树的结点数。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<5>求二叉树的叶子结点数。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<6>求二叉树的度为2的结点数。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<7>键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点,存在时要明确指出是左兄弟、左孩子、右兄弟或右孩子。
实验测试数据基本要求:
第一组数据: bt31.btr
第二组数据: bt21.btr
<8>键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息。
实验测试数据基本要求:
第一组数据: bt26.btr
第二组数据: bt21.btr
<9>将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)。
实验测试数据基本要求:
第一组数据: bt8.btr
第二组数据: bt14.btr
<10>交换二叉树中每个结点的左右孩子指针的值。(即:左子树变为右子树,右子树变为左子树)。
实验测试数据基本要求:
第一组数据: bt151.btr
第二组数据: bt21.btr
<11>复制一棵二叉树T到T1。
实验测试数据基本要求:
第一组数据: bt151.btr
第二组数据: bt21.btr
<12>输出二叉树从每个叶子结点到根结点的路径(经历的结点)。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<13>对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。(提示:需要使用队列)
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<14>对二叉链表表示的二叉树,求2个结点最近的共同祖先。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
<15>求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值。
实验测试数据基本要求:
第一组数据: bt261.btr
第二组数据: bt21.btr
3.数据结构设计
#ifndef BITREELIST_H_INCLUDED
#define BITREELIST_H_INCLUDED
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxlen 100
typedef struct LBNode
{
char data;
struct LBNode *lchild,*rchild;
}binode;
binode * creatbitree(void) //创建二叉树,链式结构
{
binode *t;
char x;
scanf("%c",&x);
if(x=='/')
{
t = NULL;
return NULL;
}
else
{
t = (binode *)malloc(sizeof(binode));
t->data = x;
t->lchild = creatbitree();
t->rchild = creatbitree();
}
return t;
}
void creatseqbitree(char arr[maxlen]) //创建二叉树,顺序结构
{
char x;
int i;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = '#';
}
i = 1;
printf("请按照从上到下的顺序依次输入二叉树各个节点,空节点用/表示,以#表示输入结束。\n");
scanf("%c",&x);
while(x!='#')
{
arr[i] = x;
scanf("%c",&x);
i++;
}
}
int readfiletoarray(char filename[],char strline[100][3],int arrlen) //文件创建二叉树
{
FILE *p;
char str[1000];
p = fopen(filename,"r");
if(p==NULL)
{
printf("文件打开失败。\n");
system("pause");
return 0;
}
if(fgets(str,1000,p)!=NULL)
{
if(strcmp(str,"BinaryTree\n")!=0)
{
printf("打开文件格式错误。\n");
fclose(p);
system("pause");
return 0;
}
}
arrlen = 0;
while(fscanf(p,"%c %c %c\n",&strline[arrlen][0],&strline[arrlen][1],&strline[arrlen][2])!=EOF)
{
arrlen++;
}
fclose(p);
return 1;
}
int row=0;
binode * creatbitreefromfile(binode *t,char strline[100][3],int len)
{
int rownext;
if((row>=len) || (len==0))
{
t = NULL;
return t;
}
t = (binode *)malloc(sizeof(binode));
t->data = strline[row][0];
t->lchild = NULL;
t->rchild = NULL;
rownext = row;
if(strline[rownext][1]=='1')
{
row++;
t->lchild = creatbitreefromfile(t->lchild,strline,len);
}
if(strline[rownext][2]=='1')
{
row++;
t->rchild = creatbitreefromfile(t->rchild,strline,len);
}
return t;
}
void destorybitree(binode *t) //销毁二叉树
{
if(t!=NULL)
{
destorybitree(t->lchild);
destorybitree(t->rchild);
free(t);
}
}
binode * maketreebyfile(void)
{
row = 0;
char filename[20];
char strline[100][3];
int arrlen,len;
binode *t;
printf("输入文件名。\n");
gets(filename);
printf("输入结点数。\n");
scanf("%d",&len);
readfiletoarray(filename,strline,arrlen);
t = creatbitreefromfile(t,strline,len);
return t;
}
void preordertraverse(binode *t); //<1>
void inordertraverse(binode *t);
void postordertraverse(binode *t);
void inordernum(binode *t,int i); //<2>
int bitreedepth(binode *t); //<3>
int nodenum=0; //<4>
void getnodenumber(binode *t); //<4>
int leafnodenum=0; //<5>
void getleafnodenumber(binode *t); //<5>
int twonodenum=0; //<6>
void intraverse(binode *t); //<6>
int searchnode(binode *t,char x); //<7>
int gethighofnode(binode *t,char x,int i); //<8>
binode * sturnintol(char arr[],int i,int a); //<9>
void slchangnode(binode *t); //<10>
void copytree(binode *t,binode *s); //<11>
void rootlongleaf(binode *t,char path[],int pathlen); //<12>
void printtree(char arr[],int a); //<13>
void lturnintos(binode *t,char arr[],int a);
void findsame(char arr[],char x,char y); //<14>
int maxlength=0; //<15>
int findmaxlength(binode *t); //<15>
void menu(void)
{
int m,n;
sta:printf("选择输入方式:<1>键盘交互创建二叉树<2>数据文件创建二叉树\n");
scanf("%d",&n);
switch(n)
{
case 1:
{
goto loop;
}
case 2:
{
goto life;
}
default:
{
printf("输入错误。\n");
system("pause");
goto sta;
}
}
loop:
printf("二叉树实验任务:\n");
printf("<1>打印出二叉树的三种遍历序。\n");
printf("<2>设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数。\n");
printf("<3>求二叉树的高度。\n");
printf("<4>求二叉树的结点数。\n");
printf("<5>求二叉树的叶子结点数。\n");
printf("<6>求二叉树的度为2的结点数。\n");
printf("<7>键盘输入一个元素x,求其父节点、兄弟结点、子结点的值。\n");
printf("<8>键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息。\n");
printf("<9>将按顺序方式存储在数组中的二叉树转换为二叉链表形式。\n");
printf("<10>交换二叉树中每个结点的左右孩子指针的值。\n");
printf("\n");
printf("二叉树选做实验:\n");
printf("<11>复制一棵二叉树T到T1。\n");
printf("<12>输出二叉树从每个叶子结点到根结点的路径。\n");
printf("<13>对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。\n");
printf("<14>对二叉链表表示的二叉树,求2个结点最近的共同祖先。\n");
printf("<15>求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值。\n");
printf("\n");
printf("<16>清屏。\n");
printf("<17>改变输入方式。\n");
printf("<18>退出。\n");
printf("\n");
scanf("%d",&m);
getchar();
printf("\n");
switch(m)
{
case 1:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
printf("\n先序遍历:\n");
preordertraverse(t);
printf("\n中序遍历:\n");
inordertraverse(t);
printf("\n后序遍历:\n");
postordertraverse(t);
destorybitree(t);
printf("\n");
system("pause");
goto loop;
}
case 2:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
int i=1;
inordernum(t,i);
destorybitree(t);
system("pause");
goto loop;
}
case 3:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
int a;
a = bitreedepth(t);
printf("二叉树的高度为:\n%d\n",a);
destorybitree(t);
system("pause");
goto loop;
}
case 4:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
nodenum=0;
getnodenumber(t);
printf("结点数为:\n%d\n",nodenum);
destorybitree(t);
system("pause");
goto loop;
}
case 5:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
leafnodenum=0;
getleafnodenumber(t);
printf("叶子结点数为:\n%d\n",leafnodenum);
destorybitree(t);
system("pause");
goto loop;
}
case 6:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
twonodenum=0;
intraverse(t);
printf("度为2的结点数为:\n%d\n",twonodenum);
destorybitree(t);
system("pause");
goto loop;
}
case 7:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
row = 0;
char x;
printf("输入结点的值:\n");
getchar();
scanf("%c",&x);
searchnode(t,x);
if(row==0)
{
printf("树中没有相应值的结点。\n");
}
destorybitree(t);
system("pause");
goto loop;
}
case 8:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
row = 0;
int i=1;
char x;
printf("输入结点的值:\n");
getchar();
scanf("%c",&x);
gethighofnode(t,x,i);
if(row==0)
{
printf("树中没有相应值的结点。\n");
}
destorybitree(t);
system("pause");
goto loop;
}
case 9:
{
binode *t;
char arr[maxlen];
int i=1,a;
creatseqbitree(arr);
for(i=1;i<maxlen;i=i+1)
{
if(arr[i]!='#')
{
a = i;
}
}
i = 1;
t = sturnintol(arr,i,a);
preordertraverse(t);
destorybitree(t);
printf("\n");
system("pause");
goto loop;
}
case 10:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
slchangnode(t);
destorybitree(t);
system("pause");
goto loop;
}
case 11:
{
binode *t,*s;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
getchar();
printf("以先序遍历的顺序向二叉树中输入元素:\n");
s = creatbitree();
copytree(t,s);
destorybitree(t);
destorybitree(s);
system("pause");
goto loop;
}
case 12:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
char path[maxlen];
int i=0,pathlen=1;
for(i=0;i<maxlen;i=i+1)
{
path[i] = '#';
}
rootlongleaf(t,path,pathlen);
destorybitree(t);
system("pause");
goto loop;
}
case 13:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
char arr[maxlen];
int i,a;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = '#';
}
i = 1;
lturnintos(t,arr,i);
for(i=0;i<maxlen;i=i+1)
{
if(arr[i]!='#')
{
a = i;
}
}
printtree(arr,a);
destorybitree(t);
system("pause");
goto loop;
}
case 14:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
char x,y;
char arr[maxlen];
int i;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = '#';
}
i = 1;
getchar();
printf("输入两个结点的值。\n");
scanf("%c %c",&x,&y);
lturnintos(t,arr,i);
findsame(arr,x,y);
destorybitree(t);
system("pause");
goto loop;
}
case 15:
{
binode *t;
printf("以先序遍历的顺序向二叉树中输入元素:\n");
t = creatbitree();
maxlength=0;
findmaxlength(t);
printf("最长的路径为:\n%d\n",maxlength);
destorybitree(t);
system("pause");
goto loop;
}
case 16:
{
system("cls");
system("pause");
goto loop;
}
case 17:
{
goto sta;
}
case 18:
{
goto mmo;
}
default:
{
printf("输入错误。\n");
system("pause");
goto loop;
}
}
life:
printf("二叉树实验任务:\n");
printf("<1>打印出二叉树的三种遍历序。\n");
printf("<2>设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数。\n");
printf("<3>求二叉树的高度。\n");
printf("<4>求二叉树的结点数。\n");
printf("<5>求二叉树的叶子结点数。\n");
printf("<6>求二叉树的度为2的结点数。\n");
printf("<7>键盘输入一个元素x,求其父节点、兄弟结点、子结点的值。\n");
printf("<8>键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息。\n");
printf("<9>将按顺序方式存储在数组中的二叉树转换为二叉链表形式。\n");
printf("<10>交换二叉树中每个结点的左右孩子指针的值。\n");
printf("\n");
printf("二叉树选做实验:\n");
printf("<11>复制一棵二叉树T到T1。\n");
printf("<12>输出二叉树从每个叶子结点到根结点的路径。\n");
printf("<13>对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。\n");
printf("<14>对二叉链表表示的二叉树,求2个结点最近的共同祖先。\n");
printf("<15>求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值。\n");
printf("\n");
printf("<16>清屏。\n");
printf("<17>改变输入方式。\n");
printf("<18>退出。\n");
printf("\n");
scanf("%d",&m);
getchar();
printf("\n");
switch(m)
{
case 1:
{
binode *t;
t = maketreebyfile();
printf("先序遍历:\n");
preordertraverse(t);
printf("\n中序遍历:\n");
inordertraverse(t);
printf("\n后序遍历:\n");
postordertraverse(t);
destorybitree(t);
printf("\n");
system("pause");
goto life;
}
case 2:
{
binode *t;
t = maketreebyfile();
int i=1;
inordernum(t,i);
destorybitree(t);
system("pause");
goto life;
}
case 3:
{
binode *t;
t = maketreebyfile();
int a;
a = bitreedepth(t);
printf("二叉树的高度为:\n%d\n",a);
destorybitree(t);
system("pause");
goto life;
}
case 4:
{
binode *t;
t = maketreebyfile();
nodenum=0;
getnodenumber(t);
printf("结点数为:\n%d\n",nodenum);
destorybitree(t);
system("pause");
goto life;
}
case 5:
{
binode *t;
t = maketreebyfile();
leafnodenum=0;
getleafnodenumber(t);
printf("叶子结点数为:\n%d\n",leafnodenum);
destorybitree(t);
system("pause");
goto life;
}
case 6:
{
binode *t;
t = maketreebyfile();
twonodenum=0;
intraverse(t);
printf("度为2的结点数为:\n%d\n",twonodenum);
destorybitree(t);
system("pause");
goto life;
}
case 7:
{
binode *t;
t = maketreebyfile();
char x;
row = 0;
printf("输入结点的值:\n");
getchar();
scanf("%c",&x);
searchnode(t,x);
if(row==0)
{
printf("树中没有相应值的结点。\n");
}
destorybitree(t);
system("pause");
goto life;
}
case 8:
{
binode *t;
t = maketreebyfile();
int i=1;
char x;
row = 0;
printf("输入结点的值:\n");
getchar();
scanf("%c",&x);
gethighofnode(t,x,i);
if(row==0)
{
printf("树中没有相应值的结点。\n");
}
destorybitree(t);
system("pause");
goto life;
}
case 9:
{
binode *t;
char arr[maxlen];
int i=1,a;
creatseqbitree(arr);
for(i=0;i<maxlen;i=i+1)
{
if(arr[i]!='#')
{
a = i;
}
}
i = 1;
t = sturnintol(arr,i,a);
preordertraverse(t);
destorybitree(t);
printf("\n");
system("pause");
goto life;
}
case 10:
{
binode *t;
t = maketreebyfile();
slchangnode(t);
destorybitree(t);
system("pause");
goto life;
}
case 11:
{
binode *t,*s;
t = maketreebyfile();
s = maketreebyfile();
copytree(t,s);
destorybitree(t);
destorybitree(s);
system("pause");
goto life;
}
case 12:
{
binode *t;
t = maketreebyfile();
char path[maxlen];
int i=0,pathlen=1;
for(i=0;i<maxlen;i=i+1)
{
path[i] = '#';
}
rootlongleaf(t,path,pathlen);
destorybitree(t);
system("pause");
goto life;
}
case 13:
{
binode *t;
t = maketreebyfile();
char arr[maxlen];
int i,a;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = '#';
}
i = 1;
lturnintos(t,arr,i);
for(i=0;i<maxlen;i=i+1)
{
if(arr[i]!='#')
{
a = i;
}
}
printtree(arr,a);
destorybitree(t);
system("pause");
goto life;
}
case 14:
{
binode *t;
t = maketreebyfile();
char x,y;
char arr[maxlen];
int i;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = '#';
}
i = 1;
getchar();
printf("输入两个结点的值。\n");
scanf("%c %c",&x,&y);
lturnintos(t,arr,i);
findsame(arr,x,y);
destorybitree(t);
system("pause");
goto life;
}
case 15:
{
binode *t;
t = maketreebyfile();
maxlength=0;
findmaxlength(t);
printf("最长的路径为:\n%d\n",maxlength);
destorybitree(t);
system("pause");
goto life;
}
case 16:
{
system("cls");
system("pause");
goto life;
}
case 17:
{
goto sta;
}
case 18:
{
goto mmo;
}
default:
{
printf("输入错误。\n");
system("pause");
goto life;
}
}
mmo: system("cls");
}
void preordertraverse(binode *t) //<1>打印出二叉树的三种遍历序。先序
{
if(t!=NULL)
{
printf("%c\t",t->data);
preordertraverse(t->lchild);
preordertraverse(t->rchild);
}
}
void inordertraverse(binode *t) //中序
{
if(t!=NULL)
{
inordertraverse(t->lchild);
printf("%c\t",t->data);
inordertraverse(t->rchild);
}
}
void postordertraverse(binode *t) //后序
{
if(t!=NULL)
{
postordertraverse(t->lchild);
postordertraverse(t->rchild);
printf("%c\t",t->data);
}
}
void inordernum(binode *t,int i) //<2>设计算法按中序次序输出二叉树中各结点的值及其所对应的层次数。
{
if(t!=NULL)
{
inordernum(t->lchild,i+1);
printf("%c\t%d\n",t->data,i);
inordernum(t->rchild,i+1);
}
}
int bitreedepth(binode *t) //<3>求二叉树的高度。
{
int m,n;
if(t==NULL)
{
return 0;
}
else
{
m = bitreedepth(t->lchild);
n = bitreedepth(t->rchild);
if(m>n)
{
return m+1;
}
else
{
return n+1;
}
}
}
void getnodenumber(binode *t) //<4>求二叉树的结点数。
{
if(t!=NULL)
{
getnodenumber(t->lchild);
nodenum++;
getnodenumber(t->rchild);
}
}
void getleafnodenumber(binode *t) //<5>求二叉树的叶子结点数。
{
if(t!=NULL)
{
getleafnodenumber(t->lchild);
getleafnodenumber(t->rchild);
if(t->lchild==NULL && t->rchild==NULL)
{
leafnodenum++;
}
}
}
void intraverse(binode *t) //<6>求二叉树的度为2的结点数。
{
if(t!=NULL)
{
intraverse(t->lchild);
if(t->lchild!=NULL && t->rchild!=NULL)
{
twonodenum++;
}
intraverse(t->rchild);
}
}
int searchnode(binode *t,char x) //<7>键盘输入一个元素x,求其父节点、兄弟结点、子结点的值,不存在时给出相应提示信息。对兄弟结点和孩子结点存在时
{ //要明确指出是左兄弟、左孩子、右兄弟或右孩子。
if(t!=NULL)
{
if(t->lchild!=NULL)
{
if(t->lchild->data==x)
{
printf("父结点的值为:%c\n",t->data);
if(t->rchild!=NULL)
{
printf("右兄弟结点的值为:%c\n",t->rchild->data);
}
else
{
printf("没有右兄弟。\n");
}
}
}
if(t->rchild!=NULL)
{
if(t->rchild->data==x)
{
printf("父结点的值为:%c\n",t->data);
if(t->lchild!=NULL)
{
printf("左兄弟结点的值为:%c\n",t->lchild->data);
}
else
{
printf("没有左兄弟。\n");
}
}
}
if(t->data==x)
{
row++;
if(t->lchild!=NULL)
{
printf("左孩子的值为:%c\n",t->lchild->data);
}
else
{
printf("没有左孩子。\n");
}
if(t->rchild!=NULL)
{
printf("右孩子的值为:%c\n",t->rchild->data);
}
else
{
printf("没有右孩子。\n");
}
}
searchnode(t->lchild,x);
searchnode(t->rchild,x);
return 0;
}
}
int gethighofnode(binode *t,char x,int i) //<8>键盘输入一个元素x,求其在树中的层次。不存在时给出相应提示信息。
{
if(t!=NULL)
{
if(t->data==x)
{
row++;
printf("所在的层次为:%d\n",i);
}
gethighofnode(t->lchild,x,i+1);
gethighofnode(t->rchild,x,i+1);
}
return 0;
}
binode * sturnintol(char arr[maxlen],int i,int a) //<9>将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)。
{
binode *t;
if(i<=a)
{
if(arr[i]!='#' && arr[i]!='/')
{
t = (binode *)malloc(sizeof(binode));
t->data = arr[i];
t->lchild = sturnintol(arr,2*i,a);
t->rchild = sturnintol(arr,2*i+1,a);
}
else if(arr[i]=='/')
{
t = NULL;
}
return t;
}
}
void slchangnode(binode *t) //<10>交换二叉树中每个结点的左右孩子指针的值。
{
binode *s;
if(t!=NULL)
{
slchangnode(t->lchild);
slchangnode(t->rchild);
if(t->lchild!=NULL || t->rchild!=NULL)
{
printf("结点的值为:%c\n",t->data);
s = t->lchild;
t->lchild = t->rchild;
t->rchild = s;
if(t->lchild!=NULL)
{
printf("交换后左孩子的值为:%c\n",t->lchild->data);
}
if(t->rchild!=NULL)
{
printf("交换后右孩子的值为:%c\n",t->rchild->data);
}
printf("\n");
}
}
}
void copytree(binode *t,binode *s) //<11>复制一棵二叉树T到T1。
{
if(t!=NULL && s!=NULL)
{
s->data = t->data;
printf("复制后结点的值为:%c\n",s->data);
copytree(t->lchild,s->lchild);
copytree(t->rchild,s->rchild);
}
else if(t==NULL && s!=NULL)
{
destorybitree(s);
}
else if(t!=NULL && s==NULL)
{
s = (binode *)malloc(sizeof(binode));
s->data = t->data;
s->lchild = NULL;
s->rchild = NULL;
printf("复制后结点的值为:%c\n",s->data);
copytree(t->lchild,s->lchild);
copytree(t->rchild,s->rchild);
}
}
void rootlongleaf(binode *t,char path[],int pathlen) //<12>输出二叉树从每个叶子结点到根结点的路径
{
int i;
if(t!=NULL)
{
if(t->lchild==NULL && t->rchild==NULL)
{
path[pathlen] = t->data;
pathlen++;
for(i=1;i<pathlen;i=i+1)
{
printf("%c\t",path[i]);
}
printf("\n");
}
else
{
path[pathlen] = t->data;
pathlen++;
rootlongleaf(t->lchild,path,pathlen);
rootlongleaf(t->rchild,path,pathlen);
}
}
}
void lturnintos(binode *t,char arr[],int a) //<13>对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印。
{
if(t!=NULL)
{
arr[a] = t->data;
lturnintos(t->lchild,arr,2*a);
lturnintos(t->rchild,arr,2*a+1);
}
}
void printtree(char arr[],int a)
{
int i=1,m=2;
for(i=1;i<=a;i=i+1)
{
if(i%m==0)
{
printf("\n");
m = m*2;
}
if(arr[i]!='#')
{
printf("%c\t",arr[i]);
}
}
}
void findsame(char arr[],char x,char y) //<14>对二叉链表表示的二叉树,求2个结点最近的共同祖先。
{
int i,j=0,k=0;
for(i=1;i<maxlen;i++)
{
if(arr[i]==x)
{
j = i;
}
else if(arr[i]==y)
{
k = i;
}
}
while(k!=j)
{
if(k>j)
{
k = k/2;
}
else if(j>k)
{
j = j/2;
}
}
printf("%c\n",arr[j]);
}
int findmaxlength(binode *t) //<15>求二叉树中一条最长的路径长度(边数),并输出路径上的个结点值。
{
int a,b;
if(t!=NULL)
{
printf("\n%c\n",t->data);
maxlength++;
if(bitreedepth(t->lchild)>bitreedepth(t->rchild))
{
findmaxlength(t->lchild);
}
else
{
findmaxlength(t->rchild);
}
}
}
#endif // BITREELIST_H_INCLUDED
#include"Bitreelist.h"
int main(void)
{
menu();
}
查找
1.实验目标
(1) 掌握顺序表的查找方法,尤其是二分查找方法。
(2) 掌握二叉排序树的建立及查找。
查找是软件设计中的最常用的运算,查找所涉及到的表结构的不同决定了查找的方法及其性能。二分查找是顺序表的查找中的最重要的方法,应能充分理解其实现方法和有关性能,并能借助其判定树结构来加深理解。二叉排序树结构在实验时具有一定的难度,可结合二叉树的有关内容和方法来实现。
2.实验内容和要求
实验任务
编写算法实现下列问题的求解。
(1) 对下列数据表,分别采用二分查找算法实现查找,给出查找过程依次所比较的元素(的下标),并以二分查找的判定树来解释。
第一组测试数据:
数据表为 (1,2,3,4,6,7,8,9,10,11,12,13,17,18,19,20,24,25,26,30,35,40,45,50,100)
查找的元素分别为: 2,8,20, 30,50,5,15,33,110
第二组数据:
数据表为 (2,3,5,7,8,10,12,15,18,20,22,25,30,35,40,45,50,55,60, 80,100)
查找的元素分别为: 22,8,80,3,100,1,13,120
(2) 设计出在二叉排序树中插入结点的算法,在此基础上实现构建二叉排序树的算法。
测试数据:构建二叉排序树的输入序列如下:
第一组数据:
100,150,120,50,70,60,80,170,180,160,110,30,40,35,175
第二组数据:
100,70,60,80,150,120,50,160,30,40,170,180,175,35
(3) 设计算法在二叉排序树中查找指定值的结点。
测试数据:在任务<1>中第一组测试数据所构造的二叉排序树中,分别查找下列元素: 150,70,160,190,10,55,175
(4) 设计算法在二叉排序树中删除特定值的结点。
测试数据:在任务(1)中第一组测试数据所构造的二叉排序树中,分别删除下列元素:30,150,100
(5) 已知整型数组A[1…26]递增有序,设计算法以构造一棵平衡的二叉排序树来存放该数组中的所有元素。
测试数据:数组元素分别为:
第一组数据:
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26)
第二组数据:
(1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210,231,253,277,302,328)
3.数据结构设计
#ifndef SEARCHLIST_H_INCLUDED
#define SEARCHLIST_H_INCLUDED
#include<stdio.h>
#include<stdlib.h>
#define maxlen 100
typedef struct LBNode
{
int data;
struct LBNode *lchild,*rchild;
}binode;
int binsearch(int a[],int n,int x) //<1>对下列数据表,分别采用二分查找算法实现查找,给出查找过程依次所比较的元素(的下标)
{
int mid,low=0,high=n-1;
while(low<=high)
{
mid = (low+high)/2;
if(x==a[mid])
{
printf("%d\n",mid);
return mid;
}
else if(a[mid]>x)
{
high = mid-1;
}
else
{
low = mid+1;
}
printf("%d\t",mid);
}
return 0;
}
binode * makenode(int a) //创建结点
{
binode *t;
t = (binode *)malloc(sizeof(binode));
t->lchild = NULL;
t->rchild = NULL;
t->data = a;
return t;
}
binode * findwherenode(binode *t,int a) //<2>寻找结点插入的位置
{
binode *m;
if(t!=NULL)
{
if(a<t->data)
{
if(t->lchild!=NULL)
{
m = findwherenode(t->lchild,a);
}
else
{
return t;
}
}
else
{
if(t->rchild!=NULL)
{
m = findwherenode(t->rchild,a);
}
else
{
return t;
}
}
}
}
int findhowmanynode(int a[maxlen]) //查找数组中有多少元素
{
int i,m;
for(i=0;i<maxlen;i=i+1)
{
if(a[i]==0)
{
m = i;
return m;
}
}
}
binode * makebitree(int a[maxlen]) //构建二叉排序树
{
int i=0,n;
binode *t,*p,*k;
t = makenode(a[0]);
n = findhowmanynode(a);
for(i=1;i<n;i=i+1)
{
p = findwherenode(t,a[i]);
k = makenode(a[i]);
if(p->data<k->data)
{
p->rchild = k;
}
else
{
p->lchild = k;
}
}
return t;
}
void takeinarr(int a[maxlen]) //输入数组
{
int i,m;
for(i=0;i<maxlen;i=i+1)
{
a[i] = 0;
}
printf("输入元素。(输入0停止)\n");
i = 0;
scanf("%d",&m);
while(m!=0)
{
a[i] = m;
i = i+1;
scanf("%d",&m);
}
}
void findkeynode(binode *t,int x) //(3) 设计算法在二叉排序树中查找指定值的结点。
{
if(t!=NULL)
{
if(t->data!=x)
{
if(t->data>x)
{
if(t->lchild!=NULL)
{
findkeynode(t->lchild,x);
}
else
{
printf("在二叉树中不存在相应值的结点。\n");
system("pause");
}
}
else
{
if(t->rchild!=NULL)
{
findkeynode(t->rchild,x);
}
else
{
printf("在二叉树中不存在相应值的结点。\n");
system("pause");
}
}
}
else
{
printf("查找到相应值的点。\n");
system("pause");
}
}
}
void deletenodeintree(binode *t,int x) //(4) 设计算法在二叉排序树中删除特定值的结点。
{
if(t!=NULL)
{
if(t->data!=x)
{
if(t->lchild!=NULL)
{
if(t->lchild->data==x)
{
binode *p;
p = t->lchild;
if(p->lchild==NULL && p->rchild==NULL)
{
t->data = p->data;
free(p);
t->lchild = NULL;
}
else
{
deletenodeintree(t->lchild,x);
}
}
else
{
deletenodeintree(t->lchild,x);
}
}
if(t->rchild!=NULL)
{
if(t->rchild->data==x)
{
binode *p;
p = t->rchild;
if(p->lchild==NULL && p->rchild==NULL)
{
t->data = p->data;
free(p);
t->rchild = NULL;
}
else
{
deletenodeintree(t->rchild,x);
}
}
else
{
deletenodeintree(t->rchild,x);
}
}
}
else
{
if(t->lchild==NULL && t->rchild!=NULL)
{
binode *p;
p = t->rchild;
t->data = p->data;
t->lchild = p->lchild;
t->rchild = p->rchild;
free(p);
}
else if(t->lchild!=NULL && t->rchild==NULL)
{
binode *p;
p = t->lchild;
t->data = p->data;
t->lchild = p->lchild;
t->rchild = p->rchild;
free(p);
}
else
{
binode *p;
p = t->lchild;
while(p->lchild!=NULL)
{
t->data = p->data;
t = t->lchild;
p = p->lchild;
}
if(p->rchild==NULL)
{
t->data = p->data;
t->lchild = NULL;
free(p);
}
else
{
t = t->lchild;
p = p->rchild;
t->data = p->data;
t->lchild = p->lchild;
t->rchild = p->rchild;
free(p);
}
}
}
}
}
binode * makebalancenode(int a[maxlen],int low,int high)
{
int mid;
binode *m;
mid = (low+high)/2;
m = makenode(a[mid]);
if(low<=high)
{
if(low!=mid)
{
m->lchild = makebalancenode(a,low,mid-1);
}
if(high!=mid)
{
m->rchild = makebalancenode(a,mid+1,high);
}
}
return m;
}
binode * makebalancetree(int a[maxlen]) //<5>已知整型数组A[1..26]递增有序,设计算法以构造一棵平衡的二叉排序树来存放该数组中的所有元素。
{
int low=0,high,n;
binode *t;
n = findhowmanynode(a);
high = n-1;
t = makebalancenode(a,low,high);
return t;
}
void destorybitree(binode *t) //销毁二叉树
{
if(t!=NULL)
{
destorybitree(t->lchild);
destorybitree(t->rchild);
free(t);
}
}
void preordertraverse(binode *t,int i) //按层次打印出二叉树
{
if(t!=NULL)
{
printf("%d\t%d\n",t->data,i);
preordertraverse(t->lchild,i+1);
preordertraverse(t->rchild,i+1);
}
}
void menu(void)
{
int m;
loop:
printf("查找实验任务:\n");
printf("<1>对下列数据表,分别采用二分查找算法实现查找,给出查找过程依次所比较的元素(的下标),并以二分查找的判定树来解释。\n");
printf("<2>设计出在二叉排序树中插入结点的算法,在此基础上实现构建二叉排序树的算法。\n");
printf("<3>设计算法在二叉排序树中查找指定值的结点。\n");
printf("<4>设计算法在二叉排序树中删除特定值的结点。\n");
printf("<5>已知整型数组A[1..26]递增有序,设计算法以构造一棵平衡的二叉排序树来存放该数组中的所有元素。\n");
printf("\n");
printf("<6>清屏。\n");
printf("<7>退出。\n");
printf("\n");
scanf("%d",&m);
printf("\n");
if(m==6 || m==7)
{
goto x;
}
int a[maxlen];
takeinarr(a);
x:
switch(m)
{
case 1:
{
int s,x;
s = findhowmanynode(a);
printf("输入查找元素的值:\n");
scanf("%d",&x);
binsearch(a,s,x);
goto loop;
}
case 2:
{
binode *t;
int i=1;
t = makebitree(a);
preordertraverse(t,i);
destorybitree(t);
goto loop;
}
case 3:
{
binode *t;
int x;
t = makebitree(a);
printf("输入查找元素的值:\n");
scanf("%d",&x);
findkeynode(t,x);
destorybitree(t);
goto loop;
}
case 4:
{
binode *t;
int x,i=1;
t = makebitree(a);
preordertraverse(t,i);
printf("\n");
i = 1;
printf("输入元素的值:\n");
scanf("%d",&x);
printf("\n");
deletenodeintree(t,x);
preordertraverse(t,i);
destorybitree(t);
goto loop;
}
case 5:
{
binode *t;
int i=1;
t = makebalancetree(a);
preordertraverse(t,i);
destorybitree(t);
goto loop;
}
case 6:
{
system("cls");
system("pause");
goto loop;
}
case 7:
{
goto mmo;
}
default:
{
printf("输入错误。\n");
system("pause");
goto loop;
}
}
mmo:system("cls");
}
#endif // SEARCHLIST_H_INCLUDED
#include"searchlist.h"
int main(void)
{
menu();
}
排序
1.实验目标
(1) 掌握各种内部排序算法。
(2) 理解各种内部排序算法的特性、时间性能和空间性能,在此基础上能根据具体情况选择合适的排序算法。
(3) *掌握运用实验分析算法的正确性、时间性能和空间性能的方法。
排序是软件设计中最常用的运算之一,有多种不同的算法,每种算法各有其特定性和最合适的适用范围。因此,了解这些特性对于实际应用时选择最恰当算法是软件设计中的重要技术。通过本次实验,应注意体会各种实验的性能特点,包括时间性能、空间性能以及其它相关的性能。同时,通过实验的方法来分析算法的各种性能是计算机科学与技术领域重要的手段,是研究各类问题求解的新算法所必需的技术,应引起足够的重视。
2.实验内容和要求
算法设计:设计算法实现下列问题的求解,并通过记录和分析过对给定的数据的运行过程中的比较和交换元素次数来分析算法的时间性能。
(1) 采用不同实验数据来观察快速排序的实验中比较和交换元素的次数,并分析数据的规模和初始特性与比较与交换次数之间的函数关系。
测试数据要求:至少5组以上;每组数据规模不小于100。
(2) 完成下面功能:将一个整型数组调整为这样的数组:所有3的倍数在最左边,所有除以3余1的数在中间,而所有除以3余2的数在最右边。要求算法的时间尽可能少。
测试数据:数组元素分别为:
第一组数据:
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26)
第二组数据:
(11,12,13,14,15,1,2,3,4,5,6, 10, 16, 1,22,23,2,17,18,19,20,24, 7,8,9,25,26)
第三组数据:
(5,6,7, 1,2,3,4,8,9,10,11,12,13, 16,17,18, 14, 25,26,15,19,20,21,22,23,24)
(3) 实现shell排序算法,并观察在采用不同的步长选取方法对排序过程中数据的比较和移动次数的影响。
测试数据:数组元素分别为:
第一组数据:
(180,203,32,46,25,76,17,58,99,100,11,102,13,54,75,6,27,18,19,29,2,82)
其余数据的规模应不少于第一组数。
(4) 设计算法实现快速排序,要求能用数组或树来演示排序过程,以清晰地表示出排序过程。
测试数据:
数组元素分别为:
第一组数据:
(106,213,325,446,579,654,721,870,917,510,21,632,73,14,815,316,412,18,619,720,21,808,923,25,26 )
(5)以数组和二叉树形式动态演示堆排序算法的排序过程。
测试数据:
数组元素分别为:
第一组数据:
(106,213,325,446,579,654,721,870,917,510,21,632,73,14,815,316,412,18,619,720,21,808,923,25,26)
(6)利用二路归并方法进行排序。
测试数据:
数组元素分别为:
第一组数据:
( 106,213,325,446,579,654,721,870,917,510,21,632,73,14,815,316,412,18,619,720,21,808,923,25,26 )
其余数据的规模应不少于第一组数的两倍。
3.数据结构设计
#ifndef ORDERLIST_H_INCLUDED
#define ORDERLIST_H_INCLUDED
#include<stdio.h>
#include<stdlib.h>
#define maxlen 200
typedef struct LBNode
{
int data;
struct LBNode *lchild,*rchild;
}binode;
void destorybitree(binode *t) //销毁二叉树
{
if(t!=NULL)
{
destorybitree(t->lchild);
destorybitree(t->rchild);
free(t);
}
}
int findhowmanynode(int a[maxlen]) //查找数组中有多少元素
{
int i,m;
for(i=0;i<maxlen;i=i+1)
{
if(a[i]==0)
{
m = i;
return m;
}
}
}
void makearray(int a[maxlen]) //生成随机数数组
{
int i;
for(i=0;i<maxlen;i=i+1)
{
a[i] = rand()%1000;
printf("%d\t",a[i]);
}
printf("\n\n");
}
binode * creatbitree(void) //创建二叉树,链式结构
{
binode *t;
int x;
scanf("%d",&x);
if(x==-1)
{
return NULL;
}
else
{
t = (binode *)malloc(sizeof(binode));
t->data = x;
t->lchild = creatbitree();
t->rchild = creatbitree();
}
return t;
}
int num=0;
int ss[maxlen];
int judgex(int x);
void arrayorder(int a[],int x,int y,int z) //数组排序//(1) 采用不同实验数据来观察快速排序的实验中比较和交换元素的次数,
{//并分析数据的规模和初始特性与比较与交换次数之间的函数关系。
if(x<y)
{
int m,n,i,j=0,k=y-x;
n = y-x+1;
m = a[x];
int b[n];
for(i=x+1;i<=y;i=i+1)
{
if(a[i]<m)
{
b[j] = a[i];
j = j+1;
}
else
{
b[k] = a[i];
k = k-1;
}
num++;
}
b[k] = m;
num++;
k = k+x;
j = 0;
while(ss[j]!=0)
{
j = j+1;
}
ss[j] = k;
for(i=0,j=x;j<=y;i=i+1,j=j+1)
{
a[j] = b[i];
}
for(i=0;i<z;i=i+1)
{
printf("%d\t",a[i]);
}
printf("\n");
if(judgex(k-1)==0)
{
arrayorder(a,x,k-1,z);
}
if(judgex(k+1)==0)
{
arrayorder(a,k+1,y,z);
}
}
}
int judgex(int x) //判断元素是否在数组中
{
int i;
for(i=0;ss[i]!=0;i=i+1)
{
if(ss[i]==x)
{
return 1;
}
}
return 0;
}
void threeorder(int a[],int n) //(2) 完成下面功能:将一个整型数组调整为这样的数组:所有3的倍数在最左边,
{//所有除以3余1的数在中间,而所有除以3余2的数在最右边。要求算法的时间尽可能少。
int i,j,k,m;
j = n-1;
for(i=0;i<n;i=i+1)
{
if(a[i]%3!=0)
{
while(a[j]%3!=0)
{
j = j-1;
}
if(j<i)
{
break;
}
else
{
m = a[i];
a[i] = a[j];
a[j] = m;
}
for(k=0;k<n;k=k+1)
{
printf("%d\t",a[k]);
}
printf("\n\n");
}
}
for(j=n-1;i<n;i=i+1)
{
if(a[i]%3!=1)
{
while(a[j]%3!=1)
{
j = j-1;
}
if(j<i)
{
break;
}
else
{
m = a[i];
a[i] = a[j];
a[j] = m;
}
for(k=0;k<n;k=k+1)
{
printf("%d\t",a[k]);
}
printf("\n\n");
}
}
}
void shellsort(int a[],int d,int n) //(3)实现shell排序算法,并观察在采用不同的步长选取方法对排序过程中数据的比较和移动次数的影响。
{
int i,j,k,m;
for(i=0;i<d;i=i+1)
{
for(j=i+1;j<d;j=j+1)
{
if(a[i]>a[j])
{
m = a[i];
a[i] = a[j];
a[j] = m;
num++;
}
}
}
for(m=0;m<n;m=m+1)
{
printf("%d\t",a[m]);
}
printf("\n");
while(d>=1)
{
for(i=d+1;i<n;i=i+1)
{
m = a[i];
k = i;
j = k-1;
while(a[j]>m && j>0)
{
a[k] = a[j];
j = j-1;
k = k-1;
num++;
}
a[k] = m;
for(m=0;m<n;m=m+1)
{
printf("%d\t",a[m]);
}
printf("\n");
}
d = d/2;
for(i=0;i<d;i=i+1)
{
for(j=i+1;j<d;j=j+1)
{
if(a[i]>a[j])
{
m = a[i];
a[i] = a[j];
a[j] = m;
num++;
}
}
}
}
}
int bitreedepth(binode *t) //求二叉树的高度。
{
int m,n;
if(t==NULL)
{
return 0;
}
else
{
m = bitreedepth(t->lchild);
n = bitreedepth(t->rchild);
if(m>n)
{
return m+1;
}
else
{
return n+1;
}
}
}
void hillsort(binode *p) //(5)以数组和二叉树形式动态演示堆排序算法的排序过程。
{//把结点部分变成大根堆
int a=0,b=0,c=0,m;
if(p!=NULL)
{
a = p->data;
if(p->lchild!=NULL)
{
b = p->lchild->data;
}
if(p->rchild!=NULL)
{
c = p->rchild->data;
}
if(c>a && c>b)
{
m = a;
a = c;
c = m;
}
else if(b>a && b>c)
{
m = a;
a = b;
b = m;
}
p->data = a;
if(p->lchild!=NULL)
{
p->lchild->data = b;
}
if(p->rchild!=NULL)
{
p->rchild->data = c;
}
hillsort(p->lchild);
hillsort(p->rchild);
}
}
binode * searchallhill(binode *t) //检测是否是大根堆
{
binode *m,*n;
if(t!=NULL)
{
m = t->lchild;
n = t->rchild;
if(m!=NULL && n==NULL)
{
if(m->data>t->data)
{
return t;
}
}
else if(m==NULL && n!=NULL)
{
if(n->data>t->data)
{
return t;
}
}
else if(m!=NULL && n!=NULL)
{
if(m->data>t->data || n->data>t->data)
{
return t;
}
}
else
{
return NULL;
}
m = searchallhill(t->lchild);
n = searchallhill(t->rchild);
if(m!=NULL)
{
return m;
}
else
{
return n;
}
}
}
void lturnintos(binode *t,int arr[],int i) //二叉树转化为数组
{
if(t!=NULL)
{
arr[i] = t->data;
lturnintos(t->lchild,arr,2*i);
lturnintos(t->rchild,arr,2*i+1);
}
}
void allhillsort(binode *t) //把整个二叉树变为大根堆
{
int arr[maxlen],a=1,i,m=2,k,j;
binode *p;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = 0;
}
k = bitreedepth(t);
lturnintos(t,arr,a);
printf("\n");
for(i=1;arr[i]!=0;i=i+1)
{
if(i%m==0)
{
printf("\n");
m = m*2;
for(j=0;j<k;j=j+1)
{
printf("\t");
}
k = k-1;
}
else if(i%m==1)
{
for(j=0;j<k;j=j+1)
{
printf("\t");
}
k = k-1;
}
if(arr[i]!=-1)
{
printf("%d\t",arr[i]);
}
}
printf("\n\n");
p = searchallhill(t);
while(p!=NULL)
{
m = 2;
a = 1;
k = bitreedepth(t);
hillsort(p);
lturnintos(t,arr,a);
for(i=1;arr[i]!=0;i=i+1)
{
if(i%m==0)
{
printf("\n");
m = m*2;
for(j=0;j<k;j=j+1)
{
printf("\t");
}
k = k-1;
}
else if(i%m==1)
{
for(j=0;j<k;j=j+1)
{
printf("\t");
}
k = k-1;
}
if(arr[i]!=-1)
{
printf("%d\t",arr[i]);
}
}
printf("\n\n");
p = searchallhill(t);
}
}
void mergetoc(int a[],int p,int r,int q,int s) //(6)利用二路归并方法进行排序。
{
int i,j,k;
int n1,n2;
int x,y;
n1 = r-p+1;
n2 = q-r;
int *m,*n;
m = (int *)malloc(sizeof(int)*n1);
n = (int *)malloc(sizeof(int)*n2);
for(i=0;i<n1;i=i+1)
{
x = i+p;
m[i] = a[x];
}
for(j=0;j<n2;j=j+1)
{
y = j+r+1;
n[j] = a[y];
}
i = 0;
j = 0;
k = p;
while(i<n1 && j<n2)
{
if(m[i]<n[j])
{
a[k] = m[i];
i = i+1;
}
else
{
a[k] = n[j];
j = j+1;
}
k = k+1;
}
while(i<n1)
{
a[k] = m[i];
i = i+1;
k = k+1;
}
while(j<n2)
{
a[k] = n[j];
j = j+1;
k = k+1;
}
free(m);
free(n);
}
void flmerge(int a[],int p,int q,int n) //分离数组
{
int r,i;
if(p<q)
{
r = (p+q)/2;
flmerge(a,p,r,n);
flmerge(a,r+1,q,n);
mergetoc(a,p,r,q,n);
for(i=0;i<n;i=i+1)
{
printf("%d\t",a[i]);
}
printf("\n\n");
}
}
void takeinarray(int a[maxlen]) //向数组中输入元素
{
int i=0,m;
printf("输入元素:(输入0停止)\n");
scanf("%d",&m);
for(i=0;i<maxlen;i=i+1)
{
a[i] = 0;
}
i = 0;
while(m!=0)
{
a[i] = m;
i = i+1;
scanf("%d",&m);
}
}
int creatseqbitree(int arr[maxlen]) //创建二叉树,顺序结构
{
int x,i,n;
for(i=0;i<maxlen;i=i+1)
{
arr[i] = 0;
}
i = 1;
printf("请按照从上到下的顺序依次输入二叉树各个节点,空节点用-1表示,以0表示输入结束。\n");
scanf("%d",&x);
while(x!=0)
{
arr[i] = x;
scanf("%d",&x);
i++;
}
n = i-1;
return n;
}
binode * sturnintol(int arr[maxlen],int i,int a) //将按顺序方式存储在数组中的二叉树转换为二叉链表形式。(数组中要扩展为完全二叉树)。
{
binode *t;
if(i<=a)
{
if(arr[i]!=0 && arr[i]!=-1)
{
t = (binode *)malloc(sizeof(binode));
t->data = arr[i];
t->lchild = sturnintol(arr,2*i,a);
t->rchild = sturnintol(arr,2*i+1,a);
}
else if(arr[i]==-1)
{
t = NULL;
}
return t;
}
}
void menu(void)
{
int m,i;
for(i=0;i<maxlen;i=i+1)
{
ss[i] = 0;
}
loop:
printf("排序实验任务:\n");
printf("(1)采用不同实验数据来观察快速排序的实验中比较和交换元素的次数,并分析数据的规模和初始特性与比较与交换次数之间的函数关系。\n");
printf("(2)完成下面功能:将一个整型数组调整为这样的数组:所有3的倍数在最左边,所有除以3余1的数在中间,而所有除以3余2的数在最右边。要求算法的时间尽可能少。\n");
printf("(3)实现shell排序算法,并观察在采用不同的步长选取方法对排序过程中数据的比较和移动次数的影响。\n");
printf("(4)设计算法实现快速排序,要求能用数组或树来演示排序过程,以清晰地表示出排序过程。\n");
printf("(5)以数组和二叉树形式动态演示堆排序算法的排序过程。\n");
printf("(6)利用二路归并方法进行排序。\n");
printf("\n");
printf("<7>清屏。\n");
printf("<8>退出。\n");
printf("\n");
scanf("%d",&m);
printf("\n");
for(i=0;ss[i]!=0;i=i+1)
{
ss[i] = 0;
}
switch(m)
{
case 1:
{
int a[maxlen];
num = 0;
makearray(a);
arrayorder(a,0,maxlen-1,maxlen);
printf("%d\n",num);
goto loop;
}
case 2:
{
int a[maxlen];
int n;
takeinarray(a);
n = findhowmanynode(a);
threeorder(a,n);
goto loop;
}
case 3:
{
int a[maxlen];
int d,n;
num = 0;
takeinarray(a);
n = findhowmanynode(a);
printf("输入步长。\n");
scanf("%d",&d);
shellsort(a,d,n);
printf("\n%d\n",num);
goto loop;
}
case 4:
{
int a[maxlen];
int n;
takeinarray(a);
n = findhowmanynode(a);
arrayorder(a,0,n-1,n);
goto loop;
}
case 5:
{
binode *t;
int i=1,n=0;
int a[maxlen];
n = creatseqbitree(a);
t = sturnintol(a,i,n);
i = 1;
allhillsort(t);
destorybitree(t);
goto loop;
}
case 6:
{
int a[maxlen];
int n;
takeinarray(a);
n = findhowmanynode(a);
flmerge(a,0,n-1,n);
goto loop;
}
case 7:
{
system("cls");
system("pause");
goto loop;
}
case 8:
{
goto mmo;
}
default:
{
printf("输入错误。\n");
getchar();
system("pause");
goto loop;
}
}
mmo:system("cls");
}
#endif // ORDERLIST_H_INCLUDED
#include"orderlist.h"
int main(void)
{
menu();
}