重写数据结构--二叉树

二叉树

过了太久猛一遇到还真不知道写些什么好,只记得建树,三种遍历方式,插入结点删除结点好像就变得很麻烦,但是还是要啃一下。

先实现三种遍历方式,练一下手。

前序遍历:
很简单的递归的使用,没什么难的吧,直接上代码:

void frontTraversal (BinaryTreeNode* root) {
    if (root == NULL) {
        return;
    } else {
        cout << root->value << ' ';
        frontTraversal(root->pLeft);
        frontTraversal(root->pRight);
    }
}

中序遍历:

void InOrderTraversal (BinaryTreeNode* root) {
    if (root == NULL) {
        return;
    } else {
        InOrderTraversal(root->pLeft);
        cout << root->value << ' ';
        InOrderTraversal(root->pRight);
    }
}

后序遍历:

void PostOrderTraversal (BinaryTreeNode* root) {
    if (root == NULL) {
        return;
    } else {
        PostOrderTraversal(root->pLeft);
        PostOrderTraversal(root->pRight);
        cout << root->value << ' ';
    }
}

建树的话,根据前序遍历和中序遍历可以建树

理一下思路:
思想是递归,先创建一个根节点来存前序的第一个元素,然后找到中序中前序第一个元素的位置k,然后中序里 0 ~ k-1是左子树,k - 1到结束是右子树
那么我们就知道了相对于根节点的左子树和右子树的元素的个数,然后再在前序里面进行拆分:第0个元素为根节点,从第1(index为1)个元素开始的k个元素是左子树,剩下的是右子树,然后分别对左右子树进行创建。
终止条件:
可以定义一个cnt,参数表里传入它的引用,每次创建节点就加1,每次进入函数判断一下cnt是否等于前序数组的长度,如果等于,则退出;
不过网上盛传的版本是另外一种:
传入的参数是前序和中序数组的首地址,和从首地址开始的长度,当指针为空或者长度为0时终止。

BinaryTreeNode* buildByPreAndIn(int* pre_order, int* in_order, int num) {
    if (pre_order == NULL || in_order == NULL || num <= 0)  return NULL;

    BinaryTreeNode* root = new BinaryTreeNode;
    root->value = *pre_order;
    root->pLeft = root->pRight = NULL;

    int rootPositionInOrder = -1;
    for (int i = 0; i < num; i++) {
        if (in_order[i] == root->value) {
            rootPositionInOrder = i;
            break;
        }
    }

    int num_Left  = rootPositionInOrder;
    int num_Right = num - num_Left - 1;

    int* pre_order_left  = pre_order + 1;
    int* in_order_left   = in_order;
    root->pLeft          = buildByPreAndIn(pre_order_left, in_order_left, num_Left);

    int* pre_order_right = pre_order + num_Left + 1;
    int* in_order_right  = in_order + num_Left + 1;
    root->pRight         = buildByPreAndIn(pre_order_right, in_order_right, num_Right);

    return root;
}

如果知道后序和中序,思路是一样的,直接贴代码:

BinaryTreeNode* buildByPostAndIn(int* post_order, int* in_order, int num) {
    if (post_order == NULL || in_order == NULL || num <= 0) return NULL;

    BinaryTreeNode* root = new BinaryTreeNode;
    root->value = post_order[num - 1];
    root->pLeft = root->pRight = NULL;

    int rootPositionInOrder = -1;
    for (int i = 0; i < num; i++) {
        if (in_order[i] == root->value) {
            rootPositionInOrder = i;
            break;
        }
    }

    int num_Left  = rootPositionInOrder;
    int num_Right = num - num_Left - 1;

    int* post_order_left = post_order;
    int* in_order_left   = in_order;
    root->pLeft          = buildByPostAndIn(post_order_left, in_order_left, num_Left);

    int* post_order_right = post_order + num_Left;
    int* in_order_right   = in_order + num_Left + 1;
    root->pRight          = buildByPostAndIn(post_order_right, in_order_right, num_Right);  

    return root;
}

求二叉树节点的个数:
递归就好

int getNumOfElements(BinaryTreeNode* root) {
    if (root == NULL) {
        return 0;
    } else {
        return getNumOfElements(root->pLeft) +
               getNumOfElements(root->pRight) + 1;
    }
}

求二叉树的深度:

int getDepth(BinaryTreeNode* root) {
    if (root == NULL) {
        return 0;
    } else {
        return max(getDepth(root->pLeft), getDepth(pRight)) + 1;
    }
}

求叶子节点的个数:
我自己想的是找出所有的节点的个数,然后再找出所有非叶子节点的个数然后减一下,但是看了网上的版本,这个显然更好:

int getNumOfLeaf(BinaryTreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    if (root->pLeft == root->pRight == NULL) {
        return 1;
    }
    return getNumOfLeaf(root->pLeft) + getNumOfLeaf(root->pRight);
}

基础的大概就是这些。

推荐一篇博文讲到的更详细:
http://blog.csdn.net/luckyxiaoqiang/article/details/7518888/#topic7

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值