1,对二叉树的几个相关概念的理清(概念内容均来自算法导论附录B的内容)
(1),树:是一个连通的,无回路的无向图,如果无向图是无回路但是非连通的,称为“森林“
(2),有根树和有序树
有根树是一颗自由树,它有一个与其他点不同的结点,为树的“根”,根是唯一没有双亲的结点,没有子女的结点是叶结点或外部结点。有根树结点的子女数称为结点的“度”,结点在树中的高度是结点向下到某个叶结点最长简单路径中边的条数。树的高度是根的高度,
一棵满二叉树,即每个内部结点都有两个子女的二叉树的结点个数为2^h – 1 , h为树的高度。
2,二叉树相关的算法题目:
// BiTree.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include <stack>
using namespace std;
struct BiTree
{
BiTree* m_pParent;
BiTree* m_pLeft;
BiTree* m_pRight;
int key;
int visited;//Only used in the function PostOrderNonRecursive()
};
void Print(BiTree* root)
{
printf("%d ", root->key);
}
void INORDER_TREE_WALK(BiTree* root)
{
if (NULL != root)
{
INORDER_TREE_WALK(root->m_pLeft);
Print(root);
INORDER_TREE_WALK(root->m_pRight);
}
}
void PREORDER_TREE_WALK(BiTree* root)
{
if (NULL != root)
{
Print(root);
PREORDER_TREE_WALK(root->m_pLeft);
PREORDER_TREE_WALK(root->m_pRight);
}
}
void POSTORDER_TREE_WALK(BiTree* root)
{
if (NULL != root)
{
POSTORDER_TREE_WALK(root->m_pLeft);
POSTORDER_TREE_WALK(root->m_pRight);
Print(root);
}
}
int IS_POSTORDER(int A[],int len)
{
int flag = 1;
int right = len - 1;
if (right > 0)
{
if (A[right] < A[len])
{
flag = 0;
}
else
{
IS_POSTORDER(A,right);
}
int left = len - 2;
if (left > 0)
{
if (A[left] > A[len])
{
flag = 0;
}
else
{
IS_POSTORDER(A,left);
}
}
}
return flag;
}
void TREE_INSERT_RECURSION(BiTree* root, int key)
{
if (root == NULL)
{
return;
}
else if (key < root->m_pLeft->key)
{
TREE_INSERT_RECURSION(root->m_pLeft,key);
}
else
{
TREE_INSERT_RECURSION(root->m_pRight,key);
}
}
BiTree* MakeNode(int key)
{
BiTree* pRoot = (BiTree*)(malloc(sizeof(BiTree)));
pRoot->m_pLeft = NULL;
pRoot->m_pRight = NULL;
pRoot->m_pParent = NULL;
pRoot->key = key;
pRoot->visited = 0;
return pRoot;
}
void DelNode(BiTree* pNode)
{
free(pNode);
}
//构建二叉查找树
void TREE_INSERT(BiTree* root, int key)
{
BiTree* y = NULL;
BiTree* x = root;
while(x != NULL)
{
y = x;
if (key < x->key)
{
x = x->m_pLeft;
}
else
{
x = x->m_pRight;
}
}
BiTree* z = MakeNode(key);
z->m_pParent = y;
if (y == NULL)
{
root = z;
}
else
{
if (key < y->key)
{
y->m_pLeft = z;
}
else
{
y->m_pRight = z;
}
}
}
//二叉查找树最小值
BiTree* TREE_MINIMUM(BiTree* root)
{
while(root->m_pLeft != NULL)
{
root = root->m_pLeft;
}
return root;
}
//二叉查找树最大值
BiTree* TREE_MAXIMUM(BiTree* root)
{
while(root->m_pRight != NULL)
{
root = root->m_pRight;
}
return root;
}
BiTree* TREE_SUCCESSOR(BiTree* node)
{
if (node->m_pRight != NULL)
{
return TREE_MINIMUM(node->m_pRight);
}
BiTree* p = node->m_pParent;
while ( p != NULL && p->m_pRight == node)
{
node = p;
p = p->m_pParent;
}
return p;
}
void TREE_DELETE(BiTree* root, BiTree* node)
{
BiTree* y = NULL;
BiTree* x = NULL;
if (node->m_pLeft == NULL || node->m_pRight == NULL)
{
y = node;
}
else
{
y = TREE_SUCCESSOR(node);
}
//开始删除
if (y->m_pLeft != NULL)
{
x = y->m_pLeft;
}
else
{
x = y->m_pRight;
}
if (x != NULL) //y是内节点
{
x->m_pParent = y->m_pParent;
}
if (y->m_pParent == NULL) // 被删除的是根节点
{
root = x;
}
else if(y == y->m_pParent->m_pLeft)
{
y->m_pParent->m_pLeft = x;
}
else
{
y->m_pParent->m_pRight = x;
}
if ( y->key != node->key )//情况3
{
node->key = y->key;
}
}
void find_dis_helper(BiTree* node, int& max_dis, int& max_depth)
{
int left_max_depth = 0;
int right_max_depth = 0;
int left_max_dis = 0;
int right_max_dis = 0;
if (node->m_pLeft != NULL)
{
find_dis_helper(node->m_pLeft,left_max_dis,left_max_depth);
}
if (node->m_pRight != NULL)
{
find_dis_helper(node->m_pRight,right_max_dis, right_max_depth);
}
max_depth = (left_max_depth > right_max_depth ? left_max_depth : right_max_depth) + 1;
int tmp_total = left_max_depth + right_max_depth + 2;
int tmp_dis = left_max_dis > right_max_dis ? left_max_dis : right_max_dis;
max_dis = max_dis > tmp_dis ? max_dis : tmp_dis;
max_dis = max_dis > tmp_total ? max_dis : tmp_total;
}
//寻找二叉树两个距离最远的结点
int Find_LONGEST_DISTANCE(BiTree* root)
{
int max_dis = 0;
int max_depth = 0;
find_dis_helper(root, max_dis, max_depth);
return max_dis;
}
//反转二叉树
void MirrorBitree(BiTree* root)
{
if (NULL == root)
{
return;
}
MirrorBitree(root->m_pLeft);
MirrorBitree(root->m_pRight);
BiTree* tmp = root->m_pLeft;
root->m_pLeft = root->m_pRight;
root->m_pRight = tmp;
}
void GetHeight_HELPER(BiTree* root, int& height, int& max_height)
{
if (NULL == root)
{
height--;
return;
}
int tmp_height = height + 1;
GetHeight_HELPER(root->m_pLeft, tmp_height, max_height);
GetHeight_HELPER(root->m_pRight, tmp_height, max_height);
if (max_height < height)
{
max_height = height;
}
}
int GetHeight(BiTree* root)
{
int height = 0;
int max_height = -1;
GetHeight_HELPER(root,height,max_height);
return max_height;
}
//分层打印二叉树
void PrintBitreeByLevel(BiTree* root, int level)
{
if (level == 0)
{
printf("%d ",root->key);
}
if (root->m_pLeft != NULL)
{
PrintBitreeByLevel(root->m_pLeft, level - 1);
}
if (root->m_pRight != NULL)
{
PrintBitreeByLevel(root->m_pRight, level - 1);
}
}
void Visit(BiTree* node)
{
if (node != NULL )
{
printf("%d ", node->key);
}
}
void PreOrderNonRecursive(BiTree* node)
{
if(node == NULL)
return;
stack<BiTree*> handywork;
handywork.push(node);
while(!handywork.empty())
{
BiTree* current = handywork.top();
handywork.pop();
Visit(current);
if(current->m_pRight)
handywork.push(current->m_pRight);
if(current->m_pLeft)
handywork.push(current->m_pLeft);
}
}
void InOrderNonRecursive(BiTree* node)
{
if(node == NULL)
return;
BiTree* current = node;
stack<BiTree*> handywork;
while(current != NULL || !handywork.empty())
{
if(current)
{
handywork.push(current);
current = current->m_pLeft;
}
else
{
current = handywork.top();
handywork.pop();
Visit(current);
current=current->m_pRight;
}
}
}
void PostOrderNonRecursive(BiTree* node)
{
if(node == NULL)
return;
BiTree* current = node;
stack<BiTree*> handywork;
while(current!= NULL )
{
handywork.push(current);
current = current->m_pLeft;
}
while(!handywork.empty())
{
BiTree* current = handywork.top();
if( !current->m_pRight || current->m_pRight->visited )
{
handywork.pop();
Visit(current);
}
else//若它的右孩子存在且rvisited为0,说明以前还没有动过它的右孩子,于是就去处理一下其右孩子。
{
//此时我们要从其右孩子结点开始一直往左下方走,直至走到尽头,将这条路径上的所有结点都入栈。
//当然,入栈之前要先将该结点的rvisited设成1,因为其右孩子的入栈意味着它的右孩子必将先于它被访问(这很好理解,因为我们总是从栈顶取出元素来进行visit)。由此可知,下一次该元素再处于栈顶时,其右孩子必然已被visit过了,所以此处可以将rvisited设置为1。
current->m_pRight->visited = 1;
current = current->m_pRight;
while(current)
{
handywork.push(current);
current = current->m_pLeft;
}
}
}
}
int main(int argc, char* argv[])
{
int a[] = {10,5,12,4,7};
BiTree* root = MakeNode(a[0]);
for (int i = 1; i < 5; i++)
{
TREE_INSERT(root,a[i]);
}
printf("InOrder\r\n");
INORDER_TREE_WALK(root);
printf("\r\n");
InOrderNonRecursive(root);
printf("\r\n");
printf("PreOrder\r\n");
PREORDER_TREE_WALK(root);
printf("\r\n");
PreOrderNonRecursive(root);
printf("\r\n");
printf("PostOrder\r\n");
POSTORDER_TREE_WALK(root);
printf("\r\n");
PostOrderNonRecursive(root);
printf("\r\n");
int A[] = {4, 7, 5, 12, 10};
printf("%d\r\n", IS_POSTORDER(A,4));
printf("%d\r\n",Find_LONGEST_DISTANCE(root));
PrintBitreeByLevel(root, 1);
MirrorBitree(root);
PrintBitreeByLevel(root, 1);
printf("\r\n height = %d", GetHeight(root));
return 0;
}