| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 584 人关注过本帖
标题:二叉排序树(求助各位大神,我写了一点但是功能不全,希望大神可以补一下)
只看楼主 加入收藏
龙牙
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:大汉
等 级:贵宾
威 望:17
帖 子:769
专家分:6207
注 册:2013-3-18
结帖率:92.86%
收藏
已结贴  问题点数:10 回复次数:3 
二叉排序树(求助各位大神,我写了一点但是功能不全,希望大神可以补一下)
   使用二叉链表存储二叉排序树,主要功能有:生成一棵二叉排序树T;计算二叉排序树T的平均查找长度,输出结果;插入元素x,重新计算二叉排序树T的平均查找长度以及统计各结点所在的层次;输入元素x,查找二叉排序树T:若存在含x的结点,则删除该结点;否则输出信息“无x”;判断二叉排序树T是否为平衡二叉树;遍历二叉排序树等;
      实现图形化操作界面;将二叉排序树调整为平衡二叉树

程序
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<stack>

#define LH +1
#define EH 0
#define RH -1
#define NULL 0

using namespace std;

typedef struct BSTNode {
    int data;     
    int bf;                         //节点的平衡因子
    struct BSTNode *lchild,*rchild;    //左右孩子指针
}BSTNode,*BSTree;


void CreatBST(BSTree &T);        //创建平衡二叉树
void R_Rotate(BSTree &p);         //对以*p为根的二叉排序树作右旋处理
void L_Rotate(BSTree &p);         //对以*p为根的二叉排序树作左旋处理
void LeftBalance(BSTree &T);      //对以指针T所指结点为根的二叉树作左平衡旋转处理
void RightBalance(BSTree &T);    //对以指针T所指结点为根的二叉树作右平衡旋转处理
bool InsertAVL(BSTree &T,int e,bool &taller);          //插入结点e
bool SearchBST(BSTree &T,int key);                 //查找元素key是否在树T中
void LeftBalance_div(BSTree &p,int &shorter);        //删除结点时左平衡旋转处理
void RightBalance_div(BSTree &p,int &shorter);       //删除结点时右平衡旋转处理
void Delete(BSTree q,BSTree  &r,int &shorter);       //删除结点
int DeleteAVL(BSTree &p,int x,int &shorter);          //平衡二叉树的删除操作
void PrintBST(BSTree T,int m);                     //按树状打印输出二叉树的元素

void preOrder(BSTree T)     //非递归前序遍历
{
    stack<BSTree> s;
    BSTree p=T;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}
void inOrder(BSTree T)      //非递归中序遍历
{
    stack<BSTree> s;
    BSTree p=T;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;
        }
    }   
}
void postOrder(BSTree T)     //非递归后序遍历
{
    stack<BSTree> s;
    BSTree c;                      //当前结点
    BSTree e=NULL;                 //前一次访问的结点
    if(T){
      s.push(T);
    }
    while(!s.empty())
    {
        c=s.top();
        if((c->lchild==NULL&&c->rchild==NULL)||
           (e!=NULL&&(e==c->lchild||e==c->rchild)))
        {
            cout<<c->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过
              s.pop();
            e=c;
        }
        else
        {
            if(c->rchild!=NULL)
                s.push(c->rchild);
            if(c->lchild!=NULL)   
                s.push(c->lchild);
        }
    }   
}



void CreatBST(BSTree &T)
{
    int depth;
    int e;
    bool taller=false;
    T = NULL;
    printf("\n请输入关键字(继续输入关键字按回车,输入-0则生成二叉树):");
    scanf("%d",&e);
    getchar();
    while(e != -0)
    {
        
        InsertAVL(T,e,taller);
        printf("\n请输入关键字(继续输入关键字按回车,输入-0则生成二叉树):");
        scanf("%d",&e);
        getchar();
        taller=false;
    }
    depth=0;
    printf("\n****************************************************\n");
    printf("                 二叉树的遍历结果为\n");
    printf("\n先根遍历:");
    preOrder(T);
    printf("\n中根遍历:");
    inOrder(T);
    printf("\n后根遍历:");
    postOrder(T);
    printf("\n");
    printf("\n****************************************************\n");
    printf("                 您创建的二叉树为\n");
    if(T)
        PrintBST(T,depth);
    else
        printf("这是一棵空树!\n");
}

void R_Rotate (BSTree &p)    //对以*p为根的二叉排序树作右旋处理
{
    BSTree lc;
    lc=p->lchild;
    p->lchild=lc->rchild;
    lc->rchild=p;
    p=lc;
}

void L_Rotate(BSTree &p)   //对以*p为根的二叉排序树作左旋处理
{
    BSTree rc;
    rc=p->rchild;
    p->rchild=rc->lchild;
    rc->lchild=p;
    p=rc;
}

void LeftBalance(BSTree &T)    //对以指针T所指结点为根的二叉树作左平衡旋转处理
{
    BSTree lc,rd;
    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(BSTree &T)     //对以指针T所指结点为根的二叉树作右平衡旋转处理
{
    BSTree rc,ld;
    rc=T->rchild;
    switch(rc->bf)
    {
    case RH:
        T->bf=rc->bf=EH;
        L_Rotate(T);
        break;
    case LH:
        ld=rc->lchild;
        switch(ld->bf)
        {
        case RH:T->bf=LH;rc->bf=EH;break;
        case EH:T->bf=rc->bf=EH;break;
        case LH:T->bf=EH;rc->bf=RH;break;
        }
        ld->bf=EH;
        R_Rotate(T->rchild);
        L_Rotate(T);
    }
}

bool InsertAVL(BSTree &T,int e,bool &taller)  //插入结点e
{
    if(!T)
    {
        T=(BSTree)malloc(sizeof(BSTNode));
        T->data=e;
        T->lchild=T->rchild=NULL;
        T->bf=EH;
        taller=true;
    }
    else{
        if(e==T->data)
        {
            taller=false;
            printf("已存在相同关键字的结点!\n");
            return 0;
        }
        if(e<T->data)
        {
            if(!InsertAVL(T->lchild,e,taller))
                return 0;
            if(taller)
                switch(T->bf)
            {
                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;
            if(taller)
                switch(T->bf)
            {
                case LH:
                    T->bf=EH;taller=false;break;
                case EH:
                    T->bf=RH;taller=true;break;
                case RH:
                    RightBalance(T);taller=false;break;
            }
        }
    }
}

bool SearchBST(BSTree &T,int key)   //查找元素key是否在树T中
{
    if(!T)
        return false;
    else if(key==T->data)
        return true;
    else if(key<T->data)
        return SearchBST(T->lchild,key);
    else
        return SearchBST(T->rchild,key);
}
void LeftBalance_div(BSTree &p,int &shorter)     //删除结点时左平衡旋转处理
{
    BSTree  p1,p2;
    if(p->bf==1)
    { p->bf=0; shorter=1; }
    else if(p->bf==0)
    { p->bf=-1; shorter=0; }
    else  
    {
        p1=p->rchild;
        if(p1->bf==0)
        {
            L_Rotate(p);
            p1->bf=1; p->bf=-1; shorter=0;
        }
        else if(p1->bf==-1)
        {
            L_Rotate(p);
            p1->bf=p->bf=0; shorter=1;
        }
        else
        {
            p2=p1->lchild;
            p1->lchild=p2->rchild; p2->rchild=p1; p->rchild=p2->lchild; p2->lchild=p;
            if(p2->bf==0)
            { p->bf=0; p1->bf=0; }
            else if(p2->bf==-1)
            { p->bf=1;p1->bf=0; }
            else
            { p->bf=0;p1->bf=-1; }
            p2->bf=0; p=p2; shorter=1;
        }
  }
}
void RightBalance_div(BSTree &p,int &shorter)    //删除结点时右平衡旋转处理
{
    BSTree  p1,p2;
    if(p->bf==-1)
    { p->bf=0; shorter=1; }
    else if(p->bf==0)
    { p->bf=1; shorter=0; }
    else
    {
        p1=p->lchild;
        if(p1->bf==0)
        {
            R_Rotate(p);
            p1->bf=-1; p->bf=1; shorter=0;
        }
        else if(p1->bf==1)
        {
            R_Rotate(p);
            p1->bf=p->bf=0; shorter=1;
        }
        else
        {
            p2=p1->rchild;
            p1->rchild=p2->lchild; p2->lchild=p1; p->lchild=p2->rchild; p2->rchild=p;
            if(p2->bf==0)
            { p->bf=0; p1->bf=0; }
            else if(p2->bf==1)
            { p->bf=-1; p1->bf=0; }
            else
            { p->bf=0; p1->bf=1; }
            p2->bf=0; p=p2; shorter=1;
        }
    }
}
void Delete(BSTree q,BSTree  &r,int &shorter)         //删除结点
{
    if(r->rchild==NULL)
    {
        q->data=r->data; q=r;
        r=r->lchild; free(q);
        shorter=1;
    }
    else
    {
        Delete(q,r->rchild,shorter);
        if(shorter==1)
            RightBalance_div(r,shorter);
    }
}
int DeleteAVL(BSTree &p,int x,int &shorter)      //平衡二叉树的删除操作
{
    int k;
    BSTree q;
    if(p==NULL)  { printf("不存在要删除的关键字!\n"); return 0;}
    else if(x<p->data)
    {
        k=DeleteAVL(p->lchild,x,shorter);
        if(shorter==1)
            LeftBalance_div(p,shorter);
        return k;
    }
    else if(x>p->data)
    {
        k=DeleteAVL(p->rchild,x,shorter);
        if(shorter==1)
            RightBalance_div(p,shorter);
        return k;
    }
    else
    {
        q=p;
        if(p->rchild==NULL)
        { p=p->lchild; free(q); shorter=1; }
        else if(p->lchild==NULL)
        { p=p->rchild; free(q); shorter=1; }
        else
        {
            Delete(q,q->lchild,shorter);
            if(shorter==1)
                LeftBalance_div(p,shorter);
            p=q;
        }
       return 1;
    }
}

void PrintBST(BSTree T,int depth)
{
    int i;
        if(T->rchild)
            PrintBST(T->rchild,depth+1);
        for(i=1;i<=depth;i++)
            printf("     ");
        printf("%d\n",T->data);
        if(T->lchild)
            PrintBST(T->lchild,depth+1);
}

//主函数
void main()
{
    BSTree T;
    int sear,cmd,depth;
    char ch;
    int shorter=0;
    bool taller=false;
    T=(BSTree)malloc(sizeof(BSTNode));
    T=NULL;

    do
    {   
        printf("\t\t\t   程序主菜单\n");
        printf("\t☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n");
            printf("\t★                                              ★\n");
        printf("\t☆\t  1. 输入节点生成二叉树及遍历           ☆\n");
            printf("\t★                                              ★\n");
        printf("\t☆\t  2. 查找并删除节点                     ☆\n");
            printf("\t★                                              ★\n");
            printf("\t☆\t  3. 插入节点                           ☆\n");
            printf("\t★                                              ★\n");
        printf("\t☆\t  4. 清空并结束                         ☆\n");
            printf("\t★                                              ★\n");
        printf("\t☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆\n");
        printf("请输入上述序号进行操作:");
        scanf("%d",&cmd);
        getchar();
        switch(cmd)
        {
        case 1:
            CreatBST(T);break;
        case 2:
            depth=0;
            printf("请输入要查找的关键字:");
                scanf("%d",&sear);getchar();
            if(SearchBST(T,sear))   
            {    DeleteAVL(T,sear,shorter);
            PrintBST(T,depth);
            printf("关键字%d已找到!\n",sear);}
            else printf("查找失败!\n");
            break;
        case 3:
            printf("请输入要插入的关键字:");
                scanf("%d",&sear);getchar();
            InsertAVL(T,sear,taller);depth=0;
            PrintBST(T,depth);
            break;
        
        case 4:
            printf("结束!\n");
            break;
        default:
            printf("输入错误!\n");
        }
        if(cmd==5)
            break;
        printf("\n继续吗? y/n:");
        scanf("%s",&ch);
        getchar();
        printf("\n");
    }while(ch=='y');
    printf("\n");
}
搜索更多相关主题的帖子: include 二叉树 平衡 统计 
2014-07-01 21:49
蚕头燕尾
Rank: 10Rank: 10Rank: 10
来 自:Gryffindo
等 级:贵宾
威 望:12
帖 子:734
专家分:1546
注 册:2013-3-24
收藏
得分:5 
你觉得你哪部分没写好?


学习编程,为的是表达自己的思想,而不是被别人的思想所禁锢。要先明白自己想干嘛,而不要先问别人让你干嘛。               

                                                                                                                    Black Cat      Hello Tomorrow~
2014-07-02 21:32
龙牙
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:16
dongshimou
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:44
专家分:152
注 册:2014-1-8
收藏
得分:5 

你可以搜一下 SBT。明显比普通BST 优秀。
个人更喜欢撸红黑。
2014-07-03 09:52
快速回复:二叉排序树(求助各位大神,我写了一点但是功能不全,希望大神可以补一 ...
数据加载中...
 
   



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

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