二叉搜索树转化为双向链表
void _revertToDoubleList(struct node *root, struct node** prev ) {
if (root == NULL) {
return;
}
revertToDoubleList(root->left, prev);
root->left = *prev;
if (prev != NULL && *prev != NULL)
(*pre)->right = root;
*pre = root;
revertToDoubleList(root->right, prev);
}
struct node * revertToDoubleList(struct node *root) {
if (root == NULL)
return NULL;
struct node *prev = NULL;
_revertToDoubleList(root, prev);
struct node *head = root, *tail = root;
while (tail->right != NULL) {
tail = tail->right;
}
head->left = tail;
tail->right = head;
return head;
}
二叉树翻转
struct node * reverseTree(struct node *root)
{
if (root == NULL) {
return NULL;
}
struct node *left = node->left;
struct node *right = node->right;
root->left = right;
root->right = left;
reverseTree(left);
reverseTree(right);
}
最近公共节点
出口
- 没有找到a或b,则返回NULL;
- 碰到a或b,就立刻返回
实现
struct node* findLowestCommonAncestor(struct node* root, struct node *node1, struct node *node2) {
if (root == NULL)
return NULL;
if (root == node1 || root == node2) {
return root;
}
sturct node *left = findLowestCommonAncestor(root->left, node1, node2);
sturct node *right = findLowestCommonAncestor(root->right, node1, node2);
if (left && right)
return root;
return left? left:right;
}
比较两棵二叉树
int compare(struct node *node2, struct node*node1) {
if (node2 == node1) {
if (node1 == NULL) {
return 1;
} else {
return compare(node1->left, node2->left) &&
compare(node1->right, node2->right);
}
}
return 0;
}
获取二叉树的宽度
int getWidth(struct node *root)
{
if (root == NULL) {
return 0;
}
if (root->left == NULL && root->right == NULL) {
return 1;
} else {
return getWidth(root->left) + getWidth(root->right);
}
}
获取二叉树的高度
int getHeight(struct node *root)
{
if (root == 0)
return NULL;
int left = getHeight(root->left);
int right=getRight(root->right);
return max(left, right) + 1;
}
二叉搜索树的后序遍历结果
思路
- 二叉的特点为:左子树均小于当前节点,右子树均大于当前节点。
实现
bool verifySequeceOfBST(int *sequece, int start, int end)
{
if (sequece == NULL ||start > end || start < 0 ||end < 0) {
return false;
}
bool left = true, right = true;
int i = 0, middle = 0;
while (i < end && sequece[i] <= sequece[end]) {
i++;
}
middle = i - 1;
while (i < end && sequece[i] > sequece[end]) {
i++;
}
if (i != end) {
return false;
}
if (middle > start) {
left = verifySequeceOfBST(sequece, start, middle);
}
if (middle < end - 1) {
right = verifySequeceOfBST(sequece, middle + 1, end - 1);
}
return (left && right);
}
二叉树中和为某一值的所有路径
思路
- 采用前序遍历的方式遍历树,利用vector来存储一条路径
- 当遇到子节点的数值小于指定和,将当前节点加入路径,继续遍历;若大于指定和,则不需要继续遍历该棵子树的路径。
- 当遇到叶子节点时,判断当前的路径和是否为指定的和,若为指定的和,则打印;
- 遍历完左右子树后,需要将当前的节点从路径中删除。
算法实现
void printPath(vector<int> path)
{
cout << "Path:>";
for (vector<int>::iterator iter = path.begin(); iter != path.end(); iter++) {
cout << *iter << " ";
}
cout << endl;
}
void findFixedSumPath(BTreeNode<int> *root, int currentSum, int sum, vector<int>& path) {
if (root == NULL) {
return;
}
currentSum += root->value;
if (currentSum <= sum) {
path.push_back(root->value);
}
if (root->isLeaf() && currentSum == sum) {
printPath(path);
}
findFixedSumPath(root->left, currentSum, sum, path);
findFixedSumPath(root->right, currentSum, sum, path);
path.pop_back();
}
有n个元素的完全二叉树的深度
完全二叉树:若设二叉树的高度为H,除第H层外,其它各层(1~H-1)的节点数都达到最大个数,第H层有叶子节点,并且叶子节点都是从左到右一次排布。判断方法:二叉树的所有子树要么没有孩子,要么一定有左孩子;二叉树要么没有子树,要么一定左右子树都有;
特点:叶子节点只可能在最大的两层上出现,对任意节点,若其右分支下的子孙最大层为L,则左分支下的子孙最大层为L或L+1
第i层最多有2^(i-1)个节点,共i层的完全二叉树最多有2^i - 1个节点。
前序遍历、中序遍历和后序遍历的互求方法
Answer:
一、已知前序、中序遍历,求后序遍历--结果唯一
例:前序遍历:GDAFEMHZ; 中序遍历:ADEFGHMZ
step1:由前序遍历可知G为root节点。
step2:由中序遍历得知:ADEF必为root的左子树,HMZ必然是root的右子树。
step3:观察左子树:ADEF。左子树的根节点,必为root的左子结点,而大树的左子结点紧接着G,故而D为左子树的根节点。
step4:同理可得M为右子树的根节点。
step5:根据上面过程递归得出:
① 确定根,确定左子树,确定右子树;
② 在左子树中递归
③ 在右子树中递归
④ 打印当前根
根据上述过程,可以画出二叉树的形状:
即后序遍历为:AEFDHZMG
二、已知中序和后序遍历,求前序遍历--结果唯一
例:中序遍历:ADEFGHMZ;后序遍历:AEFDHZMG
step1: 根据后序遍历的特点,可知最后一个节点为root节点,即root节点为G
step2:观察中序遍历,可知ADEF为左子树,HMZ为右子树
step3:观察左子树ADEF,在后序遍历中,左子树的根节点位于遍历的最后,故而D为根节点;同理可得,M为右子树的根节点;
step4:经过观察得出,确认子树的过程是递归的。递归过程如下:
① 确定根,确定左子树,确定右子树;
② 在左子树中递归
③ 在右子树中递归
④ 打印当前根
由此可得出前序遍历的结果为:GDAFEMHZ
三、已知前序遍历和后序遍历,求中序遍历--结果不唯一
二分搜索
int binary_search (int *data, int len, int key)
{
int left, right, middle;
int ret = -1;
if (data == NULL || len <= 0) {
return ret;
}
left = 0;
right = len;
while (left < right) {
middle = (left+right)/2;
if (data[middle] < key) {
left = middle+1;
} else if (data[middle] > key) {
right = middle;
} else {
return middle;
}
}
return ret;
}
前序遍历
过程
- 先遍历节点,在分别遍历左右子节点
方法
- 将root节点压栈;
- 循环直到栈为空:
- pop() 取出node
- 现将右子结点压栈,再将左子结点压栈----左子结点先出栈,先遍历!
代码实现
void prev_scan (node_t * node)
{
struct stack *s = NULL;
if (node == NULL)
return;
printf("prev_scan\n");
s = create_stack();
if (s == NULL) {
printf("Create stack failed!\n");
return;
}
push(&s, node);
while (!is_empty(s)) {
node = pop(&s);
printf("%d\t", node->value);
if (node->right) {
push(&s, node->right);
}
if (node->left) {
push(&s, node->left);
}
}
printf("\n");
destroy_stack(&s);
}
中序遍历
过程
- 先遍历左子结点,在遍历节点,最后遍历右子结点
方法
- 循环将节点的左子结点压栈,直到左子结点为空
- 出栈,打印该节点
- 将该节点赋值为右子结点,继续循环。
代码实现
void mid_scan (node_t * node)
{
struct stack *s = NULL;
if (node == NULL)
return;
printf("mid_scan\n");
s = create_stack();
if (s == NULL) {
printf("Create stack failed!\n");
return;
}
while (node || !is_empty(s)){
while (node) {
push(&s, node);
node = node->left;
}
node = pop(&s);
printf("%d\t", node->value);
node = node->right;
}
printf("\n");
destroy_stack(&s);
}
后序遍历
过程
- 先遍历左子结点,在遍历右子节点,最后遍历结点
方法
- 将该节点的左子结点循环压栈,直到左子结点为空;
- 查看当前栈顶元素:
- 若当前栈有右子结点,并且该右子节点没有打印过。则将该节点赋值为右子节点,继续1
- 若当前栈没有右子结点,或者右子节点已经打印过,则出栈,并打印该节点。然后对prev赋值为当前节点,cur赋值为null
代码实现
void post_scan (node_t * root)
{
struct stack *s = NULL;
node_t *prev = NULL, *cur = root;
if (root == NULL)
return;
printf("post_scan\n");
s = create_stack();
if (s == NULL) {
printf("Create stack failed!\n");
return;
}
while(cur || !is_empty(s)){
while(cur) {
push(&s,cur);
cur = cur->left;
}
cur = top(s);
if (cur->right == NULL || cur->right == prev) {
pop(&s);
printf("%d\t", cur->value);
prev = cur;
cur = NULL;
}else {
cur = cur->right;
}
}
printf("\n");
destroy_stack(&s);
}
找出二叉树的深度
分析
- 一个二叉树的深度等于max{左子树的深度,右子树的深度}+1
代码实现
struct node{
int value;
struct node *left;
struct node *right;
};
int get_depth(struct node *root)
{
int left = 0, right = 0 ;
if(root == NULL){
return 0;
}
left = get_depth(root->left);
right = get_depth(root->right);
return left > right? left+1: right+1;
}