二叉树
过了太久猛一遇到还真不知道写些什么好,只记得建树,三种遍历方式,插入结点删除结点好像就变得很麻烦,但是还是要啃一下。
先实现三种遍历方式,练一下手。
前序遍历:
很简单的递归的使用,没什么难的吧,直接上代码:
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