最近在写这学期学的数据结构综合性实验,本来整个程序在一周前就写出来了,可是由于其他原因,还没来得及写实验报告,昨晚跟今天一整个下午一直在写报告,发现其中很多漏洞,,,一个是插入新节点后旋转子树中写漏了一点,,因为自己测试了几组数据,发现居然运行不了,也是醉了,然后改了回来,然后通过好久,终于把实验报告写完了;下面是我写的整个程序,部分参考书上代码,如有错误,忘指出。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
#define MAXQsize 100 //队列空间初始化分配量
#define LH +1 //左边高
#define RH -1 //右边高
#define EH 0 //等高
bool taller ; //树是否长高
typedef int ElemType;
typedef int Status;
int flag=0;//查找的标记
int l=0; //左子树的深度
int r=0; //有子树的深度
int jiedian=0; //树的节点数
typedef int ElemType;
typedef struct BiTNode
{
ElemType data;
int bf; //平衡因子
int out; //后序遍历的非递归算法的标记(是否访问过)
struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree; //树的结构
struct SqStack //顺序栈
{
BiTree *base; // 在栈构造之前和销毁之后,base的值为NULL
BiTree *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
};
struct Queue // 顺序队列
{
BiTree base[MAXQsize];
int front; // 对头指针
int rear; // 队尾指针指针
};
void R_Rotate(BiTree &p)
{
//对以p为根的二叉排序树做右旋转处理,处理之后,p指向新的树根节点,
//即选择处理之前的左子树根节点。
BiTree lc;
lc = (BiTree)malloc(sizeof(BiTNode));
lc = p->lchild;
p->lchild = lc->rchild;
lc->rchild = p;
p =lc;
}
void L_Rotate(BiTree &p)
{
//对以p为根的二叉排序树做左旋转处理,处理之后,p指向新的树根节点,
//即选择处理之前的右子树根节点。
BiTree lc;
lc = (BiTree)malloc(sizeof(BiTNode));
lc = p->rchild;
p->rchild = lc->lchild ;
lc->lchild = p;
p =lc;
}
void LeftBalance(BiTree &T)
{
//对以指针T所指节点为根的二叉排序树左左平衡旋转处理,本算法结束时,
//指针T指向新的根节点。
BiTree lc,rd;
lc = rd =(BiTree)malloc(sizeof(BiTNode));
lc = T->lchild;
switch(lc->bf)
{
case LH:
T->bf = lc->bf = EH;
R_Rotate(T);
break;
case RH:
rd = lc->rchild;
switch(rd->bf)
{
case LH:
T->bf = RH;
lc->bf = EH;
break;
case EH:
T->bf = lc->bf = EH;
break;
case RH:
T->bf = EH;
lc->bf = LH;
break;
}
rd->bf = EH;
L_Rotate(T->lchild);
R_Rotate(T);
}
}
void RightBalance(BiTree &T)
{
BiTree R,Rl;
R=(T)->rchild; /* R指向T的右子树根结点 */
switch(R->bf)
{ /* 检查T的右子树的平衡度,并作相应平衡处理 */
case RH: /* 新结点插入在T的右孩子的右子树上,要作单左旋处理 */
(T)->bf=R->bf=EH;
L_Rotate(T);
break;
case LH: /* 新结点插入在T的右孩子的左子树上,要作双旋处理 */
Rl=R->lchild; /* Rl指向T的右孩子的左子树根 */
switch(Rl->bf)
{ /* 修改T及其右孩子的平衡因子 */
case RH: (T)->bf=LH;
R->bf=EH;
break;
case EH: (T)->bf=R->bf=EH;
break;
case LH: (T)->bf=EH;
R->bf=RH;
break;
}
Rl->bf=EH;
R_Rotate((T)->rchild); /* 对T的右子树作右旋平衡处理 */
L_Rotate(T); /* 对T作左旋平衡处理 */
}
}
Status InsertAVL(BiTree &T,int e,bool &taller)
{
//若二叉排序树中不存在e相同的值,则插入,并且返回1;否则返回0;
//taller 反应树长高与否。
if(!T)
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data =e;
T->out = 0;
T->lchild = T->rchild =NULL;
T->bf =EH;
taller =TRUE;
}
else
{
if(e==T->data)//树中已存在和e有相同关键字的节点。
{
taller = FALSE; //则不再插入
return 0;
}
if(e<T->data) //应在T的左子树中搜索
{
if(!InsertAVL(T->lchild,e,taller))return 0;//未插入
if(taller) //以插入到T的左子树,并且左子树长高
switch (T->bf) //检测T的平衡度
{
case LH: //原本左子树比右子树高,左平衡处理
LeftBalance(T);
taller =FALSE;
break;
case EH: //原本等高,现在因左子树增高而使得树增高
T->bf = LH;
taller = TRUE;
break;
case RH://原本右子树比左子树高,现在因右子树增高而使得树增高
T->bf = EH;
taller =FALSE;
break;
}
}
else
{
if(!InsertAVL(T->rchild,e,taller))return 0;//应在T的右子树中搜索
if(taller) //类似上面代码
switch (T->bf)
{
case LH:
T->bf = EH;
taller =FALSE;
break;
case EH:
T->bf = LH;
taller = TRUE;
break;
case RH:
RightBalance(T);
taller =FALSE;
break;
}
}
}
return 1;
}
Status InitQueue(Queue &Q)//初始化队列
{
Q.front=0;
Q.rear=0;
return OK;
}
Status InitStack(SqStack &S)//初始化栈
{
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTree));
if(!S.base) return ERROR;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status Enqueue(Queue &Q,BiTree T){
//如果入队列没有满,则T入队
if(Q.rear==MAXQsize)return ERROR;
if(T)Q.base[Q.rear++]=T;
return OK;
}
Status Delqueue(Queue &Q){
//如果队列Q不为空,则输出对头数据,左右子树入队,对头出队。
if(Q.front==Q.rear)return ERROR;
else
{
printf(“%d “,Q.base[Q.front]->data);
Enqueue(Q,Q.base[Q.front]->lchild);//入队左子树
Enqueue(Q,Q.base[Q.front]->rchild);//入队右子树
Q.front++;
}
return OK;
}
Status QueueEmpty(Queue Q){
//判断队列是否为空是返回1,否则返回0;
if(Q.front==Q.rear)return OK;
else return ERROR;
}
Status StackEmpty(SqStack S){
//判断队列是否为空是返回1,否则返回0;
if(S.top==S.base)return OK;
else return ERROR;
}
Status Push(SqStack &S,BiTree e)//入栈
{
// 在栈S中插入元素e为新的栈顶元素
*S.top++=e;
return OK;
}
Status Pop(SqStack &S,BiTree &e)//出栈
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
e=*(–S.top);
return OK;
}
BiTree Getop(SqStack &S)//返回栈顶元素
{
// 若栈不空,则返回S的栈顶元素;否则返回NULL;
if(S.top==S.base) return NULL;
return *(S.top-1);
}
Status SearchBST(BiTree T,int key,BiTree f,BiTree &p)//搜索
{
// 构造在T中查找key,用p指向它,如果找不到,p指向最后一个查找位置。
if(!T)
{
p=f;
return FALSE;
}
else if(key==T->data)
{
p=T;
return true;
}
else if(key<T->data)
{
return SearchBST(T->lchild,key,T,p);
}
else return SearchBST(T->rchild,key,T,p);
} // CreateBiTree
Status Search(BiTree T,int key)//查找
{
if(!T)
{
return true;
}
else if(key==T->data)
{
flag=1;
return true;
}
else if(key<T->data)
{
return Search(T->lchild,key);
}
else return Search(T->rchild,key);
}
Status Visit( ElemType e ) // 输出元素e的值
{
printf(“%d “, e );
return OK;
}// PrintElement
Status PreOrderTraverse2(BiTree T){
//前序遍历二叉排序树(非递归),利用栈的先入后出的特点
//对于每个元素,先访问他的数据,然后在进栈,访问左孩子,进栈,直到左孩子为空,出栈,
//访问栈顶元素的有孩子。
SqStack S;
BiTree p;
p=(BiTree)malloc(sizeof(BiTNode));
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Visit(p->data);
Push(S,p);
p=p->lchild;
}
else
{
p = Getop(S);
Pop(S,p);
p=p->rchild;
}
}
printf(“\n”);
return OK;
}
Status InOrderTraverse2(BiTree T){
//中序遍历二叉排序树(非递归)
//对于每个元素,先进栈,直到左孩子为空,出栈,访问栈顶元素的数据。
SqStack S;
BiTree p;
p=(BiTree)malloc(sizeof(BiTNode));
InitStack(S);
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;
}
}
printf(“\n”);
return OK;
}
Status PostOrderTraverse2(BiTree T){
//后序遍历二叉排序树(非递归)
//这里用out做了一个标记
//判断是否访问过
SqStack S;
BiTree p;
p=(BiTree)malloc(sizeof(BiTNode));
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p&&!p->out)
{
Push(S,p);
p=p->lchild;
}
else
{
p = Getop(S);
if(p->out)
{
Visit(p->data);
Pop(S,p);
p=NULL;
}
else
{
p->out=1;
p=p->rchild;
}
}
}
printf(“\n”);
return OK;
}
Status PreOrderTraverse( BiTree T ){
//前序遍历二叉排序树
// 前序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
if(T)
{
if(Visit(T->data))
{
if(PreOrderTraverse(T->lchild))
{
if(PreOrderTraverse(T->rchild))
return OK;
else return ERROR;
}
else return ERROR;
}
else return ERROR;
}
else return OK;
} // PreOrderTraverse
Status InOrderTraverse( BiTree T ){
//中序遍历二叉排序树
// 中序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
if(T)
{
if(InOrderTraverse(T->lchild))
if(Visit(T->data))
if(InOrderTraverse(T->rchild))
return OK;
return ERROR;
}
else return OK;
} // InOrderTraverse
Status PostOrderTraverse( BiTree T ){
//后序遍历二叉排序树
// 后序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
if(T)
{
if(PostOrderTraverse(T->lchild))
if(PostOrderTraverse(T->rchild))
if(Visit(T->data))
return OK;
return ERROR;
}
else return OK;
} // PostOrderTraverse
Status Delete(BiTree & p) {
//删除节点
//从二叉排序树中删除节点p,并重新连接它的左或右子树
BiTree q,s;
q = s = (BiTree)malloc(sizeof(BiTNode));
if(!p->rchild) //右子树空则只需重新接它的左子树
{
q = p;
p = p->lchild;
free(q);
}
else if(!p->lchild) //只需重新接它的右子树
{
q = p;
p = p->rchild;
free(q);
}
else
{
q = p;
s = p->lchild;
while(s->rchild)
{
q = s;
s = s->rchild;
}
p->data = s->data;
if(q!=p)q->rchild = s->lchild;
else q->lchild = s->lchild;
free(s);
}
return TRUE;
}
Status DeleteBST(BiTree &T,int key) {
//删除关键字
//若二叉排序树中存在于关键字Key相等的数据元素,则删除它并返回TRUE;否则返回FALSE
if(!T)return FALSE;
else
{
if(key==T->data)return Delete(T);
else if(key<T->data)return DeleteBST(T->lchild,key);
else return DeleteBST(T->rchild,key);
}
}
//Funtion One
void InitBitree(BiTree &T) //初始化二叉排序树
{
int i,n,a;
T=NULL;
scanf(“%d”,&n);
for(i=1; i<=n; i++)
{
scanf(“%d”,&a);
InsertAVL(T,a,taller);
}
}
//Funtion Two
void PreAndInAndPost_OrderTraverse(BiTree &T) {
//函数封装
//前中后遍历二叉排序树(递归)
printf(“以下三行为递归遍历结果。\n”);
PreOrderTraverse(T);
printf(“\n”);
InOrderTraverse(T);
printf(“\n”);
PostOrderTraverse(T);
printf(“\n”);
}
//Funtion Three
void SearchInBitree(BiTree &T)
{
//在树中查找关键字
//这里使用while(1)来不断查找,当输入不为Y时,退出查找
getchar();
int c;
char ch;
while(1)
{
printf(“输入Y表示继续查找,否则退出查找。\n输出1表示找到,0表示找不到!\n”);
scanf(“%ch”,&ch);
if(ch!=’Y’)break;
getchar();
if(ch==’Y’)
{
scanf(“%d”,&c);
Search(T,c);//查找元素
printf(“%d\n”,flag);
if(flag==1)flag=0;
getchar();
}
}
}
//Funtion Four
void InsertOne(BiTree &T)
{
//插入一个新的元素
int t;
printf(“请输入需要插入的元素。回车结束。\n”);
scanf(“%d”,&t);
InsertAVL(T,t,taller);//调整结构
}
//Funtion Five
void PreAndInAndPost_OrderTraverse2(BiTree &T){
//函数封装,把三个非递归遍历函数给封装到一个函数里
printf(“以下三行为非递归遍历结果。\n”);
PreOrderTraverse2(T);//前序遍历二叉排序树(非递归)
InOrderTraverse2(T);//中序遍历二叉排序树(非递归)
PostOrderTraverse2(T);//后序遍历二叉排序树(非递归)
}
//Funtion Six
void Cengcibianli(BiTree &T)
{
//见名知意(233)层次遍历二叉排序树
printf(“以下为层次遍历结果。\n”);
Queue Q;
InitQueue(Q);
if(T)Enqueue(Q,T);
while(!QueueEmpty(Q))
{
Delqueue(Q);
}
printf(“\n”);
}
//Funtion Seven
Status Swap( BiTree T ){
//交换二叉排序树的左右结点,递归
if(T)
{
BiTree temp;
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
Swap(T->lchild);
Swap(T->rchild);
}
return OK;
}
//Funtion Eight
Status Qiushendu( BiTree T ) {
//求树的深度,递归
if(!T)return 0;
else
{
int l,r;
l=Qiushendu(T->lchild);
r=Qiushendu(T->rchild);
return r>l?r+1:l+1;
}
return OK;
}
//Funtion Nine
Status Qiujiedian( BiTree T ) {
//求树的节点数,这里定义了一个全局变量,直接记录节点数
if(T){if((T->lchild==NULL)&&(T->rchild==NULL))jiedian++;
else
{
Qiujiedian(T->lchild);
Qiujiedian(T->rchild);
}
}
return OK;
}
//Funtion Ten
void DeleteOne(BiTree &T)
{
//删除一个数据元素
int del;
printf(“请输入要删除的数据:”);
scanf(“%d”,&del);
DeleteBST(T,del);
printf(“删除后的前序遍历:\n”);
PreOrderTraverse(T);
}
int main()
{
BiTree T ;
InitBitree(T); //Funtion One
PreAndInAndPost_OrderTraverse(T); //Funtion Two
SearchInBitree(T); //Funtion Three
InsertOne(T); //Funtion Four
PreAndInAndPost_OrderTraverse(T); //Funtion Two
PreAndInAndPost_OrderTraverse2(T); //Funtion Five
Cengcibianli(T); //Funtion Six
Swap(T); //Funtion Seven
printf(“前中后遍历交换后的二叉排序树\n”);
PreAndInAndPost_OrderTraverse(T); //Funtion Two
Swap(T); //Funtion Seven
printf(“前中后遍历再次交换后的二叉排序树\n”);
PreAndInAndPost_OrderTraverse(T); //Funtion Two
printf(“此棵树的深度为:%d\n”,Qiushendu(T)); //Funtion Eight
Qiujiedian(T); //Funtion Nine
printf(“此棵树的叶子节点数为:%d\n”,jiedian);
DeleteOne(T); //Funtion Ten
return 0;
}
/*example:
5
7 4 9 5 8
5
6
2
*/
by:guin_guo