| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2318 人关注过本帖
标题:[求助]二叉排序树的相关问题,请各位指教
只看楼主 加入收藏
佳辛
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2006-12-20
收藏
 问题点数:0 回复次数:7 
[求助]二叉排序树的相关问题,请各位指教

  这是我的课程设计题目,下周就要结果.麻烦知道的朋友指教.谢谢!我在后边附了已经编好的程序,可是和题目要求有一定距离,现在进行不下去了.我是一个新手,C语言学的不够好.请知道的朋友帮我完善一下程序!先谢谢大家!
  二叉排序树的相关问题,具体要求如下:
  (1)使用二叉链表存储二叉排序树,主要功能有:生成一棵二叉排序树T;计算二叉排序树T的平均查找长度,输出结果;插入元素x,重新计算二叉排序树T的平均查找长度以及统计各结点所在的层次;输入元素x,查找二叉排序树T:若存在含x的结点,则删除该结点;否则输出信息“无x”;判断二叉排序树T是否为平衡二叉树;遍历二叉排序树等;
  (2)二叉排序树至少含有10个测试数据,算法对于这些合法的输入数据都能产生满足规格说明要求的结果;
  (3)算法对于精心选择的典型、苛刻而带有刁难性的几组输入数据能够得出满足规格说明要求的结果;对算法实现过程中的异常情况能给出有效信息;
  (4)假设二叉排序树中的数据元素为整数,输入时以回车符作为结束标志等;
#include <stdio.h>
#include <stdlib.h>
#define NULL 0
typedef int keytype;
typedef int elemtype;
typedef struct node
{
keytype key; /*关键字域*/
elemtype other; /*其他域*/
struct node *lchild, *rchild; /*左 右孩子指针*/
}*bistree; /*二叉排序树的结点结构*/
int BSTSearch (bistree t,keytype key) /*二叉排序树查找的非递归算法*/
{
bistree p;
p=t;
while(p!=NULL && p->key!=key)
{
if(key<p->key)
p=p->lchild; /*沿左子树查找*/
else
p=p->rchild; /*沿右子树查找*/
}
if(p!=NULL)
return(1);
else
return(0);
}
bistree BSTInsert(bistree t,bistree s) /*二叉排序树的插入的非递归算法*/
{
bistree p,q;
if(t==NULL) /*二叉排序树为空的情况*/
{
t=s;
return(t);
}
p=t; /*从根结点开始*/
while(p!=NULL)
{
q=p;
if(s->key==p->key) /*查找到返回*/
return(t);
else /*继续搜索*/
{
if(s->key<p->key) /*搜索左子树*/
p=p->lchild;
else /*搜索右子树*/
p=p->rchild;
}
}
if(s->key>q->key)
q->rchild=s;
else
q->lchild=s;
return(t);
}

void BSTCreat(bistree t) /*建立一个有n个节点的二叉排序树算法*/
{
bistree s;
keytype key; /*关键字*/
int i,n;
t=NULL;
printf("Please input the number of the nodes:\n");
scanf("%d",&n);
printf("Please input the data:\n");
for(i=1;i<=n;i++)
{
scanf("%d",&key); /*假定关键字为整型*/
s=(bistree)malloc(sizeof(bistree)); /*生成一个新结点*/
s->lchild=NULL;
s->rchild=NULL;
s->key=key; /*调用插入算法将s所指结点插入二叉排序树t中*/
t=BSTInsert(t,s);
}
}
void BSTDelete(bistree t,int key) /*二叉排序树中删除一个结点的算法*/
{
bistree p,q,s;
p=t;
q=NULL; /*p指向待比较的结点,q指向p的前驱结点*/
while(p!=NULL && p->key!=key) /*查找值域为key的结点*/
if(key<p->key)
{
q=p;
p=p->lchild;
}
else
{
q=p;
p=p->rchild;
}
if(p==NULL)
printf("Can not find node %d \n",key);
else if(p->lchild==NULL) /*被删结点无左子树*/
{
if(q==NULL) t=p->rchild; /*考虑p为根结点的情况*/
else if(q->lchild==p)
q->lchild=p->rchild; /*p为双亲的左子树*/
else
q->rchild=p->rchild; /*p为双亲的右子树*/
free(p); /*释放p结点*/
}
else if(p->rchild==NULL) /*被删除结点无右子树*/
{
if(q==NULL)
t=p->rchild; /*考虑p为根结点的情况*/
else if(q->lchild==p)
q->lchild=p->rchild; /*p为双亲的左子树*/
else
q->rchild=p->rchild; /*p为双亲的右子树*/
free(p); /*释放P结点*/
}
else /*被删除结点同时有左子树和右子树*/
{ /*查找被删除结点的左子树中的最右结点,即刚好小于key的结点,也即是p的直接前驱*/
s=p->lchild;
while(s->rchild!=NULL) /*寻找p的直接前驱s*/
s=s->rchild;
s->rchild=p->rchild; /*被删除结点的右子树作为直接前驱s的右子树*/
/*被删除结点的左子树根代替被删结点*/
if(q==NULL) /*被删结点是根结点*/
t=p->lchild;
else if(q->lchild==p) /*p为其双亲结点左子树*/
q->lchild=p->lchild;
else /*p为双亲的右子树*/
q->rchild=p->lchild;
free(p);
}
}

void BSTPrint(bistree t)
{
if(t!=NULL)
{
BSTPrint(t->lchild);
printf("%d\t",t->key);
BSTPrint(t->rchild);
}
}

void main()
{
int k;
bistree p,s1;
keytype key1;
print5f("建立二叉排序树:\n");
p=NULL;
s1=NULL;
BSTCreat(p);
printf("请输入需要查找关键字:\n");
scanf("%d",&key1);
k=BSTSearch(p,key1);
if(!k)
printf("There is no such a node.\n");
else
printf("There id such a node.\n ");
printf("请输入要插入的结点关键字的值:\n");
scanf("%d",&s1->key);
p=BSTInsert(p,s1);
printf("请输入要删除的结点关键字的值:\n");
scanf("%d",&key1);
BSTDelete(p,key1);
printf("打印输出该二叉树:\n");
BSTPrint(p);

}

搜索更多相关主题的帖子: 指教 
2006-12-20 09:53
fengwei
Rank: 1
等 级:新手上路
帖 子:57
专家分:0
注 册:2006-12-19
收藏
得分:0 
算法没注意看 。程序定义就出现大问题
void BSTDelete(bistree t,int key)

bistree 是什么类型。
结构体定义好像要用上面的 typedef struct node
bistree 仅仅是一个指向 node 类型的指针
2006-12-20 11:05
佳辛
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2006-12-20
收藏
得分:0 
谢谢fengwei,我在研究一下!
2006-12-20 11:29
fengzar1984
Rank: 1
等 级:新手上路
帖 子:19
专家分:0
注 册:2006-3-30
收藏
得分:0 
[QUOTE]这是我的课程设计题目,下周就要结果.麻烦知道的朋友指教.谢谢!我在后边附了已经编好的程序,可是和题目要求有一定距离,现在进行不下去了.我是一个新手,C语言学的不够好.请知道的朋友帮我完善一下程序!先谢谢大家!
  二叉排序树的相关问题,具体要求如下:
  (1)使用二叉链表存储二叉排序树,主要功能有:生成一棵二叉排序树T;计算二叉排序树T的平均查找长度,输出结果;插入元素x,重新计算二叉排序树T的平均查找长度以及统计各结点所在的层次;输入元素x,查找二叉排序树T:若存在含x的结点,则删除该结点;否则输出信息“无x”;判断二叉排序树T是否为平衡二叉树;遍历二叉排序树等;
  (2)二叉排序树至少含有10个测试数据,算法对于这些合法的输入数据都能产生满足规格说明要求的结果;
  (3)算法对于精心选择的典型、苛刻而带有刁难性的几组输入数据能够得出满足规格说明要求的结果;对算法实现过程中的异常情况能给出有效信息;
  (4)假设二叉排序树中的数据元素为整数,输入时以回车符作为结束标志等;
[/QUOTE]
在学习中,正好也可以练习下,平时对2x树关注的少!
2006-12-20 16:33
fengzar1984
Rank: 1
等 级:新手上路
帖 子:19
专家分:0
注 册:2006-3-30
收藏
得分:0 

二叉排序树的相关问题,具体要求如下:
  (1)a:使用二叉链表存储二叉排序树,主要功能有:生成一棵二叉排序树T;
b:计算二叉排序树T的平均查找长度,输出结果;
c:插入元素x,重新计算二叉排序树T的平均查找长度以及统计各结点所在的层次;
d:输入元素x,查找二叉排序树T:
f:若存在含x的结点,则删除该结点;否则输出信息“无x”;
g:判断二叉排序树T是否为平衡二叉树;
h:遍历二叉排序树等;
  (2)二叉排序树至少含有10个测试数据,算法对于这些合法的输入数据都能产生满足规格说明
要求的结果;
  (3)算法对于精心选择的典型、苛刻而带有刁难性的几组输入数据能够得出满足规格说明要求的
结果;对算法实现过程中的异常情况能给出有效信息;
  (4)假设二叉排序树中的数据元素为整数,输入时以回车符作为结束标志等;

名词解释:1#平衡二叉树:左右子树都是平衡二叉树,且左右子树的深度相差<=1.
2#二叉排序数:指的是一棵为空的二叉树,或者具有如下特性的非空二叉树:
1'若它的左子树非空,则左子树上所有的结点的值均小于根结点的值
2'若它的右子树非空,则右子树上所有的结点的值均大于根结点的值
3'左右子树又各是一棵二查排序数
*/
#define NULL 0

typedef struct bnode
{
int data;
struct bnode *left, *right;
}bnode,btree;

/**********对于课程设计条件可知道需要创建的函数如下*********/

//创建二叉树
void create(btree *b);

//输出二叉树结点元素
void print(btree *b);

//插入结点s
void insert(btree *b, btree *s);

//查找元素x,返回search类型指针
btree *search(btree *b, int x);

//删除元素x
void del(btree *b, int x);

//判断是否为平衡二叉树。
bool balencebtree(btree *b);

//先序遍历二叉树
void preorder(btree *b);

//二叉树的深度,关键是为了判断平衡二叉树
int depth(btree *b);

//二叉树的当前接点的层次
void level(btree *b,btree *p, int nodelevel,int currentlevel) //nodelevel初值为1
{
if (b == NULL)h = 0 ;
else if(p == b)nodelevel = currentlevel;
else
{
level(p, b->left,nodelevel,currentlevel+1);
if(h == -1)level(p,b->right,nodelevel,currentlevel+1);
}
}


/***********声明函数的实现*************/

/*
先讨论向二叉树中插入一个结点s的函数实现思想:
a:若b是空树,则将s所指的结点作为根结点插入,否则
b:若s->data = b(相对根结点)的数据域的值(无须插入相同的点),则返回;否则
c:若s->data < b的数据域的值,则把s所指结点插入到左子书中;否则
d:把s所指结点插入到有子树中。
*/

void insert(btree *b, bnode *s)
{

if(b == NULL) b = s;
else
if(s->data = b->data)
return;
else
if(s->data < b->data)
insert(b->left,s);
else
if(s->data >b->data)
insert(b->right,s);
}

/*
生成二叉树的过程先有一个空树,再逐个插入,并以-1结束
*/

void create(btree *b)
{
int x;
btree *s;
b = NULL;
do
{
scanf("%d",&x); //读入一个整数
s = (bnode *)malloc(sizeof(bnode)); //开辟一个新结点s
s ->data = x;
s ->left = NULL;
s ->right = NULL;
insert(b,s);
}while(x != -1);
}

/*
输出的是有嵌套括号的二叉树。思想:
a:首先输出根结点
b:再依次输出它的左子数和右子树
c:另外,依次输出的左右子树至少有一个不为空,否则不必输出了
*/

void print(btree *b)
{
if(b != NULL)
{
printf("%d",b ->data);
if(b ->left != NULL ||b ->right != NULL) //确定左右子树不为空
{
printf("(");
print(b ->left);
if (b ->right != NULL)
printf(",");
print(b ->right);
printf(")");
}
}
}

/*
在二叉树b中查找x的过程为:
a:若b是空树,则搜索失败,否则
b:若x等于b的根结点的数据域的值,则查找成功;否则
c:若x<b的根结点的数据域的值,则搜索左子树;否则
d:查找右子树。
*/

btree *search(btree *b, int x)
{
if(b == NULL)
return(NULL);
else
{
if(b ->data == x)return(b);
if(x <b->data)return(search(b ->left,x));
else
return(search(b->right,x));
}
}

/*
在二叉树b中删除x的过程为:
a:若b是空树,则返回printf("the btree is null!");,
b:若p所指没有左子树,则用右子树的根代替被删的结点
c:若p所指结点有左子树,则在其左子树中找到最右结点r来代替被删除的结点
(即将t所指结点的右指针置成p所指结点的右子树的根,然后用p所指结点的
左子树的根结点代替被删的p所指结点)。

*/
void del(btree *b, int x)
{
btree *p; //p指向待比较的结点
btree *q; //q指向p的前驱结点
btree *r; //有左子树时的最右结点
btree *t; //无左子树时的临时结点
p = b;
q = NULL;

while(p != NULL && p ->data != x)
if(x <p->data)
{
q = p;
p = p->left;
}
else
{
q = p;
p = p ->right;
}
if (p == NULL)
{
printf("the btree is null!");
}
else
if(p ->left == NULL) //被删除结点无左子树
{
if(q == NULL)
t = p ->right;
else if(q ->left == p)
q ->left = p ->right;
else
q ->right = p ->right;
}
/************查找被删除结点的左子树中的最右结点,即刚好小于x的结点***************/
else //被删除结点有左子树
{
r = p ->left;

while(r ->right != NULL)
r = r->right;
//被删除的右子树作为r的右子树
r ->right = p ->right;
//被删除结点的左子树根代替被删结点
if(q == NULL)t = p ->left; //被删结点是根结点
else if(q ->left == p)
q ->left = p ->left;
else q ->right = p ->left;
}
}


/*
先序遍历二叉树
*/
void preorder(btree *b)
{
if(b != NULL)
{
printf("%d",b ->data);
preorder(b ->left);
preorder(b ->right);
}
}

/**************求二叉树的深度******************/
int depth(btree *b)
{
int dep1, dep2;
if(b == NULL)return 0;
else
{
dep1 = depth(b->left);
dep2 = depth(b->right);
if(dep1 > dep2)
return (dep1+1);
else
return (dep2+1);
}

}


/**************判断平衡二叉树****************/
bool balencebtree(btree *b)
{
if(b == NULL)return true;
int dep1 = depth(b->left);
int dep2 = depth(b->right);
if((dep1-dep2) > 1 || (dep2-dep1) > 1)
return false;
else
return balencebtree(b->left)&&balencebtree(b->right);

}

2006-12-25 13:06
fengzar1984
Rank: 1
等 级:新手上路
帖 子:19
专家分:0
注 册:2006-3-30
收藏
得分:0 

像二叉树的平均查找长度,这可以单独搞好几天了

2006-12-25 13:07
龙牙
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:大汉
等 级:贵宾
威 望:17
帖 子:769
专家分:6207
注 册:2013-3-18
收藏
得分:0 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)< (b))
#define LQ(a,b) ((a)<=(b))

#define TRUE 1
#define FALSE 0
#define OVERFLOW -2



typedef int KeyType;
typedef int Status;

typedef struct{
    KeyType key; /*关键字域*/
}SElemType;
typedef struct BitNode{
    SElemType data; /*存储空间基址,建表时按实际长度分配,0号单元留空*/
    struct BitNode *lchild,*rchild;
}BitNode,* BiTree;

/*二叉排序树的插入*/
Status InsertBST(BiTree &T,KeyType key){
    BiTree s;
    if(!T){
        s=(BiTree)malloc(sizeof(BitNode));
        s->data.key=key;
        s->lchild=s->rchild=NULL;
        T=s;
    }
    else if LT(key,T->data.key)
        InsertBST(T->lchild,key);
    else InsertBST(T->rchild,key);
    return TRUE;
}
/*创建二叉排序树*/
void CreateBST(BiTree &T){
    KeyType key;
    T=NULL;
    scanf("%d",&key);
    while(key!=0){
        InsertBST(T,key);
        scanf("%d",&key);
    }
}
 
/*中序遍历*/
void InOrderTraverse(BiTree T){
    if(T){
        InOrderTraverse(T->lchild);
        printf("%4d",T->data.key);
        InOrderTraverse(T->rchild);
    }
}
/*先序遍历*/
int preordertraverse(BiTree T)
{
if(T){
   printf("%4d",T->data.key);
   if(T->lchild)
   preordertraverse(T->lchild);
   preordertraverse(T->rchild);
   return 1;
   }
  
}
/*层次遍历*/
int cctraver(BiTree T)
{
    int base,top,j;
BiTree a[100];
BiTree P;
P=T;
base=0;top=0;j=0;
if(P)
{
   a[top]=P;
   top++;
    while(P||a[top]!=a[base])
   {
    if(j>=top)break;
     if(P->lchild&&!P->rchild)
    {
       a[top]=P->lchild;
         top++;
                P=a[j+1];j++;
    }
    if(!P->lchild&&P->rchild)
     {
          a[top]=P->rchild;
          top++; P=a[j+1];j++;
     }
    if(P->lchild&&P->rchild)
     {
          a[top]=P->lchild;
          top++;
      a[top]=P->rchild;
          top++;
      P=a[j+1];j++;
     }
    if(!P->lchild&&!P->rchild)
    {P=a[j+1];j++;}
   }
        while(a[base]!=a[top])
   {
    P=a[base];
    printf("%4d",P->data.key);
      base++;
   }
}
else printf("error!");
printf("\n");
return 1;
}
/*输出二叉树*/
Status PrintTree(BiTree T,int n){
    if(T==NULL)return FALSE;
    PrintTree(T->rchild,n+1);
    for(int i=0;i<n;i++)
        printf("   ");
    printf("%d\n",T->data.key);
    PrintTree(T->lchild,n+1);
    return TRUE;
}

/*计算平均查找长度*/
 int calculateASL(BiTree *t,int *s,int *j,int i)/*计算平均查找长度*/
{
   if(*t)
   {  i++;   /*i记录当前结点的在当前树中的深度*/
      *s=*s+i;   /*s记录已遍历过的点的深度之和*/
     if(calculateASL(&(*t)->lchild,s,j,i)) /*计算左子树的ASL*/
     {
           (*j)++;   /*j记录树中结点的数目*/
           if(calculateASL(&(*t)->rchild,s,j,i)) /*计算右子树的ASL*/
           {i--; return(1);}
     }
    }
  else    return(1);
}

/*二叉排序树的查找*/
BiTree SearchBST(BiTree T,KeyType key){
    if(!T){return T;}
    else if EQ(key,T->data.key){return T;}
    else if LT(key,T->data.key) return SearchBST(T->lchild,key);
    else return SearchBST(T->rchild,key);
}


/*二叉排序树的删除*/

Status Delete(BiTree &p){
    BiTree q,s;
    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;
        delete s;
    }
    return TRUE;
}

Status DeleteBST(BiTree &T,KeyType key){
    if(!T)return FALSE;
    else{
        if (EQ(key,T->data.key))return Delete(T);
        else
            if(LT(key,T->data.key))return DeleteBST(T->lchild,key);
            else return DeleteBST(T->rchild,key);
    }
}

/*判断是否是平衡二叉树*/
int balance(BiTree T,int i,int *j)/*判断是否为平衡二叉树的函数*/
{
    int   dep1,dep2;
    if(BitNode *T)         return 0;
    else   
 {
        dep1= balance(T,2*i,j);
        dep2= balance(T,2*i+1,j);
     }
    if((dep1-dep2)>1||(dep1-dep2)<-1) *j=dep1-dep2;/*用j值记录是否存在不平衡现象*/
    if(dep1>dep2) return(dep1+1);
    else   return(dep2+1);
}

void main() {
    BiTree b1,b2;
    KeyType key;
    int t;
    int s=0;
    int i=0;
    int j=0;
    int num;
begin:
   
   
     printf("\t\t\t   程序主菜单\n");
        printf("\t☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n");
            printf("\t★\t       1:创建二叉排序树                 ★\n");
        printf("\t☆\t       2:输出排序树                     ☆\n");
            printf("\t★\t       3:查找并删除结点                 ★\n");
        printf("\t☆\t       4:二叉树遍历                     ☆\n");
            printf("\t★\t       5:插入结点                       ★\n");
        printf("\t☆\t       6:判断是否为平衡二插树           ☆\n");
            printf("\t★\t       0:退出                           ★\n");
        printf("\t☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n");
        printf("请选择要进行的操作:");
    scanf("%d",&t);
    switch(t){
    case 1:
        printf("请输入关键字(0 为结束):");
        CreateBST(b1);
        PrintTree(b1,0);//排序树的结果打输出
        calculateASL(&b1,&s,&j,i);
              printf("平均查找长度:");
                    printf("   ASL=%d/%d",s,j);
                    printf("\n");
        goto begin;
    case 2:
        PrintTree(b1,0);
              goto begin;
    case 3:
        printf("请输入要查找的关键字:");
        scanf("%d",&key);
        if(SearchBST(b1, key))
        {DeleteBST(b1, key);
            printf("\n发现该关键字\n 删除完毕!\n");
        }
        else printf("没有该关键字!!\n 删除失败\n");
        goto begin;
    case 4:printf("先序遍历");
        preordertraverse(b1);
        printf("\n");
        printf("中序遍历");
        InOrderTraverse(b1);
        printf("\n");
        printf("层次遍历");
        cctraver(b1);
        goto begin;
    case 5:
        printf("输入要插入的数据:");
        scanf("%d",&key);
        if(InsertBST(b1, key))
        printf("\n插入完毕!\n");
   
        else printf("插入失败\n");
        goto begin;
    case 6:
         num=0;
         balance(b1,1,&num);
         if(num==0)   printf("   这是一颗平衡二叉树!");
         else    printf("   这不是一颗平衡二叉树!");
         printf("\n");
         goto begin;
    case 0:goto end;break;
    default: printf("输入错误\n");
    }
end:
    printf("\n谢谢使用!\n");
}

哥们,这个程序还不全,除了插入元素x,重新计算二叉排序树T的平均查找长度以及统计各结点所在的层次;   实现图形化操作界面;将二叉排序树调整为平衡二叉树。没有实现别的都可以实现,你改改用吧

只要心是晴朗的,人生就没有雨天。
2014-07-03 09:20
龙牙
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:大汉
等 级:贵宾
威 望:17
帖 子:769
专家分:6207
注 册:2013-3-18
收藏
得分:0 
我刚才xian统计各结点所在的层次这个问题,你可以利用深度,将深度相同的输出就可以,还有用层次遍历也可以,你试一试。

只要心是晴朗的,人生就没有雨天。
2014-07-03 09:54
快速回复:[求助]二叉排序树的相关问题,请各位指教
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.036601 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved