数据结构--二叉树

1、准备工作

  • 二叉搜索树 Binary search tree
  • 每个节点的值大于其左子树,小于其右子树(左小右大)
// 二叉搜索树
typedef struct BST{
    int data;
    struct BST* left;
    struct BST* right;
}BstNode,*Bst;

//链表
typedef struct LNode {
    BstNode* bst; //保存传入的二叉树节点
    struct LNode *next;
}LNode;
//队列 ,于实现二叉树的层次遍历
typedef struct Queue{
    LNode *front; //头
    LNode *rear; //尾
}Queue;

/*队列*/
//入队   从rear入   从front出
void Enqueue (BstNode* data,Queue **Q);
//出队
void Dequeue(Queue **Q);

2、插入(递归)

void Insert(Bst *root,int data){
    if(*root == NULL){
        //申请一个新节点
        BstNode *newnode = (BstNode *)malloc(sizeof( BstNode));
        newnode->data = data;
        newnode->left = NULL;
        newnode->right = NULL;

        *root = newnode;
    }
    else if(data<(*root)->data){
        Insert( &((*root)->left), data);
    }
    else if(data>(*root)->data){
        Insert( &((*root)->right),data);
    }
}

3、查找

BstNode* Search(Bst root,int data){

    BstNode *p = root;
    while(1){
        if(p == NULL){ return NULL; }
        else if(p->data == data){ return p; }
        else if(p->data>data){ p = p->left; }
        else if(p->data<data){ p = p->right; }
    }

    /*
     //递归实现
     if(root == NULL){return NULL;}
      else if(root->data == data){return root;}
      else if(root->data > data){return Search(root->left,data);}
      else {return Search(root->right,data);}
     */
}

4、返回树的高度(递归)

  • 对于树的高度和深度说法不一,但我更倾向于这种
    一个节点的高度 = 该节点到最底层节点的边数
    一个节点的深度 = 该节点到节点的边数
    空树:节点的高度 = 深度 = -1
int FindHeight(Bst root){
    BstNode * p = root;
    if(p == NULL){
        return -1;
    }
    int l = FindHeight(p->left);
    int r =  FindHeight(p->right);
    return l>r?l+1:r+1;
}

5、二叉树的遍历(广度优先)

void PrintBST_BF(Bst root,Queue *Q){
    BstNode *p = root;
    if(p == NULL){
        printf("空树\n");
        return;
    }
    Enqueue(p,&Q);
    printf("代码判断:");
    while(Q->front != NULL){
        printf("%d",Q->front->bst->data);
        if(Q->front->bst->left != NULL){
            Enqueue(Q->front->bst->left,&Q);
        }
        if(Q->front->bst->right != NULL){
            Enqueue(Q->front->bst->right,&Q);
        }
        Dequeue(&Q);
    }
    printf("\n");
}

5、二叉树的遍历(深度优先)

  • 当前节点root 左节点left 右节点right
    root - left - right 前序遍历preorder
    left - root - right中序遍历inorder
    left - right - root 后序遍历postorder
void PrintBST_DF(Bst root,int type){

    if(root == NULL) return;

    /*前序遍历*/
    if(type == 1){
        printf("%d",root->data);
        PrintBST_DF(root->left,1);
        PrintBST_DF(root->right,1);
    }

    /*中序遍历*/
    else if(type == 2){
        PrintBST_DF(root->left,2);
        printf("%d",root->data);
        PrintBST_DF(root->right,2);
    }

    /*后序遍历*/
    else if(type == 3){
        PrintBST_DF(root->left,3);
        PrintBST_DF(root->right,3);
        printf("%d",root->data);
    }
}

6、删除一个节点(递归 难点)

BstNode * Del(Bst root,int data){
    if (root == NULL) return NULL;
    if (data > root->data) root->right = Del(root->right,data);
    else if(data < root->data) root->left = Del(root->left,data);
    else{
        //没有子节点
       if(root->left == NULL && root->right == NULL) {
           free(root);
           root = NULL;
       }
       //一个子节点
       else if(root->left == NULL){
           BstNode *p = root;
           root = root->right;
           free(p);
       }
       else if(root->right== NULL){
           BstNode *p = root;
           root = root->left;
           free(p);
       }
       //两个子节点
       else if(root->right != NULL && root->left != NULL){
           root->data = root->left->data;
           root->left = Del(root->left,root->data);
           //也可以把右节点往上移
           //root->data = root->right->data;
          // root->right = Del(root->right,root->data); 
       }
   }
    return root;
}

7、判断是否为二叉搜索树

  • 中序遍历判定
    当前节点一定大于之前节点
  • 节点区间判定
    对于左节点: 当前节点的父节点的父节点 < 当前节点 < 当前节点的父节点
    root->data < root->right->left->data < right->left->data
    对于右节点: 当前节点的父节点的父节点 < 当前节点 < 当前节点的父节点
    root->data >right->left->right->data > right->left->data
int IsBST(Bst root,int type){
    //假设二叉搜索树的值都大于0,小于1000
    if(type == 1){
        return IsBST_IN(root,0);
    }
    else if(type == 2){
        return IsBST_SE(root,0,1000);
    }
    else{
        return -1;
    }
}

/*中序遍历判定 */
int IsBST_IN(Bst root,int pre){
    if(root == NULL) return 1;
    if(IsBST_IN(root->left,pre)){
        if(root->data>pre){
            pre = root->data;
            return IsBST_IN(root->right,pre);
        } else{
            return 0;
        }
    }else{
        return 0;
    }
}
/*节点区间判定 */
int IsBST_SE(Bst root,int min,int max){
    if(root == NULL) return 1;
        if (root->data > min && max > root->data) {
            if (IsBST_SE(root->left, min, root->data)
            && IsBST_SE(root->right, root->data, max))
                return 1;
            else{
                return 0;
            }
        } else {
            return 0;
        }
}

8、完整演示

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>


//二叉搜索树 Binary search tree
// 每个节点的值大于等于其左子树,小于等于·其右子树(左小右大)
typedef struct BST{
    int data;
    struct BST* left;
    struct BST* right;
}BstNode,*Bst;

//链表
typedef struct LNode {
    BstNode* bst; //保存传入的二叉树节点
    struct LNode *next;
}LNode;
//队列 ,于实现二叉树的层次遍历
typedef struct Queue{
    LNode *front; //头
    LNode *rear; //尾
}Queue;

/*队列*/
//入队   从rear入   从front出
void Enqueue (BstNode* data,Queue **Q);
//出队
void Dequeue(Queue **Q);

/*二叉搜索树*/
//插入(递归实现)
void Insert(Bst *root,int data);
//查找(成功返回1 否则返回0)
BstNode* Search(Bst root,int data);
//找到二叉搜索树的高度(递归实现)
int FindHeight(Bst root);
//二叉树的遍历(广度优先 Breadth first)
void PrintBST_BF(Bst root,Queue *Q);
//二叉树的遍历(深度优先 Depth first)(递归)
void PrintBST_DF(Bst root,int type);
//删除一个节点
BstNode * Del(Bst root,int data);
//判断是否为二叉搜索树(中序遍历/范围判定)
int IsBST(Bst root,int type);
//判断是否为二叉搜索树(中序遍历判定)
int IsBST_IN(Bst root,int pre);
//判断是否为二叉搜索树(节点区间判定)
int IsBST_SE(Bst root,int min,int max);
//返回指定数据所在节点的中序后继节点
BstNode *FindInPrecursor(Bst root,int data);
int main() {

    /*二叉搜索树*/
    Bst root;//根节点
    root = NULL;
    int data[10] = {5,7,3,9,2,6,4,1,8,3};
    for(int i = 0;i<9;i++){
        Insert(&root,data[i]);
    }

    /*队列*/
    Queue *Q = (Queue *) malloc(sizeof(Queue));
    Q->front = NULL;
    Q->rear = NULL;
   /*高度判断与查找*/
    printf("树的高度为%d;    ", FindHeight(root));
    printf("查找 %d 返回地址:%p\n",data[9],Search(root,data[9]));
    /*遍历*/
    printf("\n深度优先遍历:理论   ->   实际   \n");
    printf("前序:532147698  ->  ");
    PrintBST_DF(root,1);
    printf("\n中序:123456789  ->  ");
    PrintBST_DF(root,2);
    printf("\n后序:124368975  ->  ");
    PrintBST_DF(root,3);
    printf("\n");
    printf("广度优先遍历:理论   ->   实际   \n");
    printf("537246918   ->   ");
    PrintBST_BF(root,Q);
    /*删除*/
    printf("\n删除 %d\n",data[9]);
    Del(root,data[9]);
    PrintBST_BF(root,Q);
    printf("查找 %d 返回地址:%p\n",data[9],Search(root,data[9]));
    /*判断是否为二叉树搜索树*/
    printf("\n判断是否为二叉搜索树:(是1 否0)\n");
    printf("中序遍历判断:%d       ",IsBST(root,1));
    printf("节点区间判断:%d\n",IsBST(root,2));

    int e = 4;
    if( FindInPrecursor(root,e) != NULL){
        printf("\n数据%d在中序遍历中的前驱节点为:%d\n",e,
               FindInPrecursor(root,e)->data);
    }


    return 0;
}

//入队
void Enqueue (BstNode* data,Queue **Q){
    LNode *tmp = (LNode *) malloc(sizeof(LNode));
    tmp->bst = data;
    tmp->next = NULL;

    if( (*Q)->front == NULL){
        (*Q)->front = tmp;
        (*Q)->rear = tmp;
        //printf("%d入队\n",tmp->bst);
    } else{
        (*Q)->rear->next = tmp;
        (*Q)->rear = tmp;
        //printf("%d入队\n",tmp->bst);
    }
}
//出队
void Dequeue(Queue **Q){

    if( (*Q)->front != NULL){
        LNode *tmp =  (*Q)->front;
        (*Q)->front =  (*Q)->front->next;
       // printf("%d出队\n",tmp->data);
        free(tmp);
    }else{
        printf("队为空\n");
        return;
    }
}

void Insert(Bst *root,int data){
    if(*root == NULL){
        //申请一个新节点
        BstNode *newnode = (BstNode *)malloc(sizeof( BstNode));
        newnode->data = data;
        newnode->left = NULL;
        newnode->right = NULL;

        *root = newnode;
    }
    else if(data<(*root)->data){
        Insert( &((*root)->left), data);
    }
    else if(data>(*root)->data){
        Insert( &((*root)->right),data);
    }
}

BstNode* Search(Bst root,int data){

    BstNode *p = root;
    while(1){
        if(p == NULL){ return NULL; }
        else if(p->data == data){ return p; }
        else if(p->data>data){ p = p->left; }
        else if(p->data<data){ p = p->right; }
    }

    /*
     //递归实现
     if(root == NULL){return NULL;}
      else if(root->data == data){return root;}
      else if(root->data > data){return Search(root->left,data);}
      else {return Search(root->right,data);}
     */
}

int FindHeight(Bst root){
    /*
     * 对于树的高度和深度说法不一
     * 一个节点的高度 = 该节点到最下层节点的边数
     * 一个节点的深度  = 该节点到根节点的边数
     * 空树 节点的高度 = 深度 = -1
     */
    BstNode * p = root;
    if(p == NULL){
        return -1;
    }
    int l = FindHeight(p->left);
    int r =  FindHeight(p->right);
    return l>r?l+1:r+1;
}

void PrintBST_BF(Bst root,Queue *Q){
    BstNode *p = root;
    if(p == NULL){
        printf("空树\n");
        return;
    }
    Enqueue(p,&Q);
    while(Q->front != NULL){
        printf("%d",Q->front->bst->data);
        if(Q->front->bst->left != NULL){
            Enqueue(Q->front->bst->left,&Q);
        }
        if(Q->front->bst->right != NULL){
            Enqueue(Q->front->bst->right,&Q);
        }
        Dequeue(&Q);
    }
    printf("\n");
}
void PrintBST_DF(Bst root,int type){
    /*根节点root 左子树left 右子树right
     * root - left - right 前序遍历preorder
     * left - root - right 中序遍历inorder
     *left - right - root 后序遍历postorder
     */
    if(root == NULL) return;

    /*前序遍历*/
    if(type == 1){
        printf("%d",root->data);
        PrintBST_DF(root->left,1);
        PrintBST_DF(root->right,1);
    }

    /*中序遍历*/
    else if(type == 2){
        PrintBST_DF(root->left,2);
        printf("%d",root->data);
        PrintBST_DF(root->right,2);
    }

    /*后序遍历*/
    else if(type == 3){
        PrintBST_DF(root->left,3);
        PrintBST_DF(root->right,3);
        printf("%d",root->data);
    }
}

BstNode * Del(Bst root,int data){
    if (root == NULL) return NULL;
    if (data > root->data) root->right = Del(root->right,data);
    else if(data < root->data) root->left = Del(root->left,data);
    else{
        //没有子节点
       if(root->left == NULL && root->right == NULL) {
           free(root);
           root = NULL;
       }
       //一个子节点
       else if(root->left == NULL){
           BstNode *p = root;
           root = root->right;
           free(p);
       }
       else if(root->right== NULL){
           BstNode *p = root;
           root = root->left;
           free(p);
       }
       //两个子节点
       else if(root->right != NULL && root->left != NULL){
           root->data = root->left->data;
           root->left = Del(root->left,root->data);
           //root->data = root->right->data;
          // root->right = Del(root->right,root->data);
       }
   }
    return root;
}


int IsBST(Bst root,int type){
    //假设二叉搜索树的值都大于0,小于1000
    if(type == 1){
        return IsBST_IN(root,0);
    }
    else if(type == 2){
        return IsBST_SE(root,0,1000);
    }
    else{
        return -1;
    }
}

/*当前节点一定大于之前节点*/
int IsBST_IN(Bst root,int pre){
    if(root == NULL) return 1;
    if(IsBST_IN(root->left,pre)){
        if(root->data>pre){
            pre = root->data;
            return IsBST_IN(root->right,pre);
        } else{
            return 0;
        }
    }else{
        return 0;
    }
}

/* 对于左节点:
 * 当前节点的父节点的父节点  < 当前节点 < 当前节点的父节点
 * root->data  < root->right->left->data < right->left->data
 *
 * 对于右节点:
 * 当前节点的父节点的父节点  < 当前节点 < 当前节点的父节点
 * root->data > right->left->right->data > right->left->data
*/
int IsBST_SE(Bst root,int min,int max){
    if(root == NULL) return 1;
        if (root->data > min && max > root->data) {
            if (IsBST_SE(root->left, min, root->data)
            && IsBST_SE(root->right, root->data, max))
                return 1;
            else{
                return 0;
            }
        } else {
            return 0;
        }
}

BstNode *FindInPrecursor(Bst root,int data){
    //找到数据节点
    BstNode *c = Search(root,data);//数据节点
    if(c == NULL){
        printf("数据 %d 不在二叉树中\n",data);
        return NULL;
    }
    //当前节点的左节点不为空,找到其左子树中的最大值
    if (c->left != NULL){
        c = c->left;
        BstNode *p = c;//前驱节点
        while(c != NULL){
            p = c;
            c = c->right;
        }
        return p;
    }
    else{
        BstNode *a = root;//数据节点的祖先节点
        BstNode *p = NULL;//前驱节点
        while (a != c){
            if(a->data < data){
                p = a;//保存较小的那个
                a = a->right;
            }
            else {
                a = a->left;
            }
        }
        if(p == NULL){
            printf("数据 %d 没有前驱节点\n",data);
        }
        return p;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值