二叉树及其基本操作

有关栈的基本操作请参考:>数据结构之栈的基本操作<
有关队列的基本操作请参考:>数据结构之队列的基本操作<

概念

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的二叉树组成。

二叉树特点:

  • 每个结点最多有两个子树,即二叉树不存在度大于2的结点
  • 二叉树的子树有左右之分,其子树的次序不能颠倒

满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子节点都在同一层上
完全二叉树:如果一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树

性质

  • 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)(i>0)个结点
  • 若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大结点数是2^k - 1(k>=0)
  • 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
  • 具有n个结点的完全二叉树的深度k为log₂(n+1)上取整
  • 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:
    1. 若i>0,双亲序号:(i-1)/2;
      i=0,i为根节点编号,无双亲结点
    2. 若2i+1 < n,左孩子序号:2i+1,否则无左孩子
    3. 若2i+2 < n,右孩子序号:2i+2,否则无右孩子

存储

二叉树主要有顺序存储链式存储结构
顺序存储结构:对于一棵完全二叉树所有结点按照层序自顶向下,同一层自左向右顺序编号,就得到一个节点的顺序序列
优点:存储完全二叉树,简单省空间
缺点:存储一般二叉树尤其单支树,存储空间利用不高

基本操作

  • 二叉树的遍历(先序,中序,后序,层序)
  • 根据先序遍历结果创建一颗二叉树(要求空结点有特殊符号表示)
  • 销毁二叉树
  • 克隆二叉树
  • 求一棵树的结点个数
  • 求一棵树叶子结点个数
  • 求一棵树第K层结点个数
  • 求二叉树的高度
  • 判断一个结点是否在一棵二叉树中
  • 获取一个结点的左孩子结点
  • 获取一个结点的右孩子结点
  • 获取一个结点的双亲结点
  • 非递归遍历二叉树(先序,中序,后序)
  • 求二叉树的镜像
  • 判断一棵二叉树是否为完全二叉树(层序遍历变形)

①bin_tree.h

#pragma once

#include <stddef.h>
#include <stdlib.h>
#include <string.h>

typedef char TreeNodeType;

typedef struct TreeNode{
    TreeNodeType data;
    struct TreeNode* lchild;
    struct TreeNode* rchild;
}TreeNode;

void TreeInit(TreeNode** root);

void PreOrder(TreeNode* root);      //先序遍历

void InOrder(TreeNode* root);       //中序遍历

void PostOrder(TreeNode* root);     //后序遍历

void LevelOrder(TreeNode* root);    //层序遍历

TreeNode* TreeCreate(TreeNodeType array[], size_t size, TreeNodeType null_node);     //通过给出遍历结果创造一棵树

void TreeDestroy(TreeNode** root);  //销毁一棵树

TreeNode* TreeClone(TreeNode* root);    //克隆一棵树

size_t TreeSize(TreeNode* root);    //求树的节点数

size_t TreeLeafSize(TreeNode* root);    //求树的叶子节点数

size_t TreeKLevelSize(TreeNode* root, int K);   //求树的第K层节点数

size_t TreeHeight(TreeNode* root);        //树的高度

TreeNode* TreeFind(TreeNode* root, TreeNodeType to_find);     //查找元素

TreeNode* LChild(TreeNode* node);       //左孩子节点

TreeNode* RChild(TreeNode* node);       //右孩子节点

TreeNode* Parent(TreeNode* root, TreeNode* node);       //父亲节点

void PreOrderByLoop(TreeNode* root);     //非递归版本的先序遍历

void InOrderByLoop(TreeNode* root);      //非递归版本的中序遍历 

void PostOrderByLoop(TreeNode* root);    //非递归版本的后序遍历

void TreeMirror(TreeNode* root);         //二叉树的镜像

int isCompleteTree(TreeNode* root);      //判断该二叉树是否是完全二叉树

②bin_tree.c

#include "bin_tree.h"

#include <stdio.h>

#include "seqqueue.h"
#include "seqstack.h"

TreeNode* CreateTreeNode(TreeNodeType value){
    TreeNode* new_node = (TreeNode*)malloc(sizeof(TreeNode));
    new_node->data = value;
    new_node->lchild = NULL;
    new_node->rchild = NULL;
    return new_node;
}

void DestroyTreeNode(TreeNode* ptr){
    free(ptr);
}

void TreeInit(TreeNode** root){
    if(root == NULL){
        return;
    }
    *root = NULL;
}

void PreOrder(TreeNode* root){
    if(root == NULL){
        return;
    }
    printf("%c ",root->data);
    PreOrder(root->lchild);
    PreOrder(root->rchild);
}

void InOrder(TreeNode* root){
    if(root == NULL){
        return;
    }
    InOrder(root->lchild);
    printf("%c ",root->data);
    InOrder(root->rchild);
}

void PostOrder(TreeNode* root){ 
    if(root == NULL){
        return;
    }
    PostOrder(root->lchild);
    PostOrder(root->rchild);
    printf("%c ",root->data);
}

void LevelOrder(TreeNode* root){
    if(root == NULL){
        //空树
        return;
    }
    SeqQueue q;
    SeqQueueInit(&q);
    //1.先把根节点插入到队列
    SeqQueuePush(&q, root);
    //2.循环取队首元素
    TreeNode* cur = NULL;
    while(SeqQueueFront(&q, &cur)){
         //3.访问队首元素并出队列
         printf("%c ", cur->data);
         SeqQueuePop(&q);
         //4.将队首元素的左右子树依次入队列
         if(cur->lchild != NULL){
             SeqQueuePush(&q, cur->lchild);
         }
         if(cur->rchild != NULL){
             SeqQueuePush(&q, cur->rchild);
         }
         //5.进入下一次循环,直到队列为空
    }
}

TreeNode* _TreeCreate(TreeNodeType array[], size_t size, size_t* index, TreeNodeType null_node){
    if(index == NULL){
        return NULL;    //非法输入
    }
    if(*index >= size){
        //构建已完成
        return NULL;
    }
    if(array[*index] == null_node){
        return NULL;
    }
    TreeNode* new_node = CreateTreeNode(array[*index]);
    ++(*index);
    new_node->lchild = _TreeCreate(array,size,index,null_node);
    ++(*index);
    new_node->rchild = _TreeCreate(array,size,index,null_node);
    return new_node;
}

TreeNode* TreeCreate(TreeNodeType array[], size_t size, TreeNodeType null_node){
    //当前读到了数组的第几个元素
    size_t index = 0;
    return _TreeCreate(array, size, &index, null_node);
}

void TreeDestroy(TreeNode** root){
    if(root == NULL){
        return;    //非法输入
    }
    if(*root == NULL){
        return;
    }
    TreeNode* to_delete = *root;
    TreeNode* to_delete_lchild = to_delete->lchild;
    TreeNode* to_delete_rchild = to_delete->rchild;
    DestroyTreeNode(to_delete);
    TreeDestroy(&to_delete_lchild);
    TreeDestroy(&to_delete_rchild);
    *root = NULL;
}

TreeNode* TreeClone(TreeNode* root){
    if(root == NULL){
        return NULL;
    }
    TreeNode* new_root = CreateTreeNode(root->data);
    new_root->lchild = TreeClone(root->lchild);
    new_root->rchild = TreeClone(root->rchild);
    return new_root;
}

//size_t TreeSize(TreeNode* root){
//    if(root == NULL){
//        return 0;
//    }
//    return 1 + TreeSize(root->lchild) + TreeSize(root->rchild);
//}
//
void _TreeSize(TreeNode* root,size_t* size){
    if(root == NULL || size == NULL){
        return;    //非法输入
    }
    //访问当前元素,每次访问一个就把size++
    ++(*size);
    _TreeSize(root->lchild,size);
    _TreeSize(root->rchild,size);
}

size_t TreeSize(TreeNode* root){
    size_t size = 0;
    _TreeSize(root,&size);
    return size;
}

size_t TreeLeafSize(TreeNode* root){
    if(root == NULL){
        return 0;
    }
    if(root->lchild == NULL && root->rchild == NULL){
        return 1;
    }
    return TreeLeafSize(root->lchild) + TreeLeafSize(root->rchild);
}

size_t TreeKLevelSize(TreeNode* root, int K){
    if(root == NULL || K < 1){
        return 0;
    }
    if(K == 1){
        return 1;
    }
    return TreeKLevelSize(root->lchild, K - 1) + TreeKLevelSize(root->rchild, K - 1);
}

size_t TreeHeight(TreeNode* root){
    if(root == NULL){
        return 0;
    }
    size_t lheight = TreeHeight(root->lchild);
    size_t rheight = TreeHeight(root->rchild);
    return lheight > rheight ? lheight + 1 : rheight + 1;
}

TreeNode* TreeFind(TreeNode* root, TreeNodeType to_find){
    if(root == NULL){
        return NULL;
    }
    if(root->data == to_find){
        return root;
    }
    TreeNode* lresult = TreeFind(root->lchild, to_find);
    TreeNode* rresult = TreeFind(root->rchild, to_find);
    return lresult != NULL ? lresult : rresult;
}

TreeNode* LChild(TreeNode* node){
    if(node == NULL){
        return NULL;
    }
    return node->lchild;
}

TreeNode* RChild(TreeNode* node){
    if(node == NULL){
        return NULL;
    }
    return node->rchild;
}

TreeNode* Parent(TreeNode* root, TreeNode* node){
    if(root == NULL || node == NULL){
        return NULL;
    }
    if(root->lchild == node || root->rchild == node){
        return root;
    }
    TreeNode* lresult = Parent(root->lchild, node);
    TreeNode* rresult = Parent(root->rchild, node);
    return lresult != NULL ? lresult : rresult;
}

void PreOrderByLoop(TreeNode* root){
    if(root == NULL){
        return;
    }
    SeqStack stack;
    SeqStackInit(&stack);
    SeqStackPush(&stack, root);
    while(1){
        TreeNode* top = NULL;
        SeqStackTop(&stack, &top);
        if(top == NULL){
            //遍历完
            break;
        }
        //访问当前栈顶元素
        printf("%c ", top->data);
        //将栈顶元素出栈
        SeqStackPop(&stack);

        //把当前元素右子树和左子树分别入栈
        if(top->rchild != NULL){
            SeqStackPush(&stack, top->rchild);
        }
        if(top->lchild != NULL){
            SeqStackPush(&stack, top->lchild);
        }
    }
    printf("\n");
}

void InOrderByLoop(TreeNode* root){
    if(root == NULL){
        return;
    }
    SeqStack stack;
    SeqStackInit(&stack);
    TreeNode* cur = root;
    while(1){
        //1.从根结点出发,尝试找到当前树的最左侧节点 
        //  每次经过一个节点,就把这个节点入栈
        while(cur != NULL){
            SeqStackPush(&stack, cur);
            cur = cur->lchild;
        }
        //2.取栈顶元素,访问,并将该元素出栈
        TreeNode* top = NULL;
        SeqStackTop(&stack, &top);
        if(top == NULL){
            //遍历结束
            break;
        }
        printf("%c ", top->data);
        SeqStackPop(&stack);
        //3.处理当前元素的右子树,回到循环开始,再去找右子树的最左节点
        cur = top->rchild;
    }
    printf("\n");
    return;
}

void PostOrderByLoop(TreeNode* root){
    if(root == NULL){
        return;
    }
    SeqStack stack;
    SeqStackInit(&stack);
    TreeNode* cur = root;
    TreeNode* pre = NULL;
    while(1){
        while(cur != NULL){
            SeqStackPush(&stack, cur);
            cur = cur->lchild;
        }
        TreeNode* top = NULL;
        SeqStackTop(&stack, &top);
        if(top == NULL){
            break;
        }
        //取出栈顶元素后,满足以下两个条件之一,才能访问top
        //1.top 的右子树为空
        //2.top 的右子树被访问过
        //否则就需要处理 top 的右子树
        if(top->rchild == NULL || top->rchild == pre){
            printf("%c ", top->data);
            SeqStackPop(&stack);
            pre = top;
        }
        else{
            cur = top->rchild;
        }
    }
    printf("\n");
}

void TreeMirror(TreeNode* root){
    if(root == NULL){
        return;
    }
    TreeNode* tmp = root->lchild;
    root->lchild = root->rchild;
    root->rchild = tmp;
    TreeMirror(root->lchild);
    TreeMirror(root->rchild);
}

int isCompleteTree(TreeNode* root){
    if(root == NULL){
        return -1;
    }
    SeqQueue queue;
    SeqQueueInit(&queue);
    SeqQueuePush(&queue, root);
    int flag = 0;      //此标志是为了判断当前节点的两个孩子节点是否为空
    while(1){
        TreeNode* top = NULL;
        SeqQueueFront(&queue, &top);
        if(top == NULL){
            //遍历完了
            break;
        }
        //访问当前节点
        if(flag == 0){
            if(top->lchild != NULL && top->rchild != NULL){
                SeqQueuePush(&queue, top->lchild);
                SeqQueuePush(&queue, top->rchild);
            }
            else if(top->lchild == NULL && top->rchild != NULL){
                return 0;
            }
            else if(top->lchild != NULL && top->rchild == NULL){
                SeqQueuePush(&queue, top->lchild);
                flag = 1;
            }
            else if(top->lchild == NULL && top->rchild == NULL){
                flag = 1;
            }
        }
        else{
            if(top->lchild == NULL && top->rchild == NULL){
                //说明到目前为止还满足完全二叉树的条件
            }
            else{
                return 0;
            }
        }
        SeqQueuePop(&queue);
    }
    return 1;
}

③test.c

#include "bin_tree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TEST_HEADER printf("\n========================%s====================\n",__FUNCTION__)

void TestInit(){
    TEST_HEADER;
    TreeNode* root;
    TreeInit(&root);
    printf("root expect NULL, actual %p\n",root);
}

void TestPreOrder(){
    TEST_HEADER;
    TreeNode* root;
    TreeInit(&root);
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->rchild = f;
    root = a;

    printf("[先序遍历结果]:");
    PreOrder(root);
    printf("\n");
}

void TestInOrder(){
    TEST_HEADER;
    TreeNode* root;
    TreeInit(&root);
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->rchild = f;
    root = a;

    printf("[中序遍历结果]:");
    InOrder(root);
    printf("\n");
}

void TestPostOrder(){
    TEST_HEADER;
    TreeNode* root;
    TreeInit(&root);
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->rchild = f;
    root = a;

    printf("[后序遍历结果]:");
    PostOrder(root);
    printf("\n");
}

void TestLevelOrder(){
    TEST_HEADER;
    TreeNode* root;
    TreeInit(&root);
    TreeNode* a = CreateTreeNode('a');
    TreeNode* b = CreateTreeNode('b');
    TreeNode* c = CreateTreeNode('c');
    TreeNode* d = CreateTreeNode('d');
    TreeNode* e = CreateTreeNode('e');
    TreeNode* f = CreateTreeNode('f');
    TreeNode* g = CreateTreeNode('g');
    a->lchild = b;
    a->rchild = c;
    b->lchild = d;
    b->rchild = e;
    e->lchild = g;
    c->rchild = f;
    root = a;

    printf("[层序遍历结果]:");
    LevelOrder(root);
    printf("\n");
}

void TestCreate(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array,strlen(array),'#');

    printf("[先序遍历结果]:");
    PreOrder(root);
    printf("\n");

    printf("[中序遍历结果]:");
    InOrder(root);
    printf("\n");

    printf("[后序遍历结果]:");
    PostOrder(root);
    printf("\n");
}

void TestDestroy(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array,strlen(array),'#');

    TreeDestroy(&root);
    printf("root expect NULL, actual %p\n", root);
}

void TestClone(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array,strlen(array),'#');

    TreeNode* new_root = TreeClone(root);
    printf("new_root: %p, root: %p\n",new_root,root);

    printf("[先序遍历结果]:");
    PreOrder(new_root);
    printf("\n");

    printf("[中序遍历结果]:");
    InOrder(new_root);
    printf("\n");

    printf("[后序遍历结果]:");
    PostOrder(new_root);
    printf("\n");
}

void TestSize(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array,strlen(array),'#');
    printf("size expect 7, actual %lu\n",TreeSize(root));
}

void TestLeafSize(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("leafsize expect 3, actual %lu\n", TreeLeafSize(root));
}

void TestKLevelSize(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("3LevelSize expect 3, actual %lu\n", TreeKLevelSize(root, 3));
}

void TestHeight(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("height expect 4, actual %lu\n", TreeHeight(root));
}

void TestFind(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    TreeNode* find = TreeFind(root, 'd');
    printf("find->data expect d, actual %c\n", find->data);
}

void TestLChild(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    TreeNode* find = TreeFind(root, 'b');
    TreeNode* lchild = LChild(find);
    printf("lchild->data expect d, actual %c\n", lchild->data);
}

void TestRChild(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    TreeNode* find = TreeFind(root, 'b');
    TreeNode* rchild = RChild(find);
    printf("rchild->data expect e, actual %c\n", rchild->data);
}

void TestParent(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    TreeNode* find = TreeFind(root, 'b');
    TreeNode* parent = Parent(root, find);
    printf("b parent expect a, actual %c\n", parent->data);

    find = TreeFind(root, 'f');
    parent = Parent(root, find);
    printf("f parent expect c, actual %c\n", parent->data);
}

void TestPreOrderByLoop(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("[先序遍历结果]:");
    PreOrderByLoop(root);
}

void TestInOrderByLoop(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("[中序遍历结果]:");
    InOrderByLoop(root);
}

void TestPostOrderByLoop(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    printf("[后序遍历结果]:");
    PostOrderByLoop(root);
}

void TestMirror(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    TreeMirror(root);
    printf("[先序遍历结果]:");
    PreOrderByLoop(root);
    printf("[中序遍历结果]:");
    InOrderByLoop(root);
    printf("[后序遍历结果]:");
    PostOrderByLoop(root);
}

void TestIsCompleteTree(){
    TEST_HEADER;
    TreeNodeType array[] = "abd##eg###c#f##";
    TreeNode* root = TreeCreate(array, strlen(array), '#');
    int ret = isCompleteTree(root);
    printf("ret expect 0, actual %d\n", ret);

    TreeNodeType array1[] = "abd##e##cf###";
    TreeNode* root1 = TreeCreate(array1, strlen(array1), '#');
    ret = isCompleteTree(root1);
    printf("ret expect 1, actual %d\n", ret);
}

int main(){
    TestInit();
    TestPreOrder();
    TestInOrder();
    TestPostOrder();
    TestLevelOrder();
    TestCreate();
    TestDestroy();
    TestClone();
    TestSize();
    TestLeafSize();
    TestKLevelSize();
    TestHeight();
    TestFind();
    TestLChild();
    TestRChild();
    TestParent();
    TestPreOrderByLoop();
    TestInOrderByLoop();
    TestPostOrderByLoop();
    TestMirror();
    TestIsCompleteTree();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值