二叉樹的創建
二叉樹創建的方式有很多種,可以根據先根遍歷的序列和中根遍歷的序列對二叉樹進行創建,也可以給一個特定的先序序列對二叉樹進行創建。用先根序列和中根序列創建二叉樹,就是先根序列的第一個元素一定是樹的根節點,然後再中根序列中找到這個根節點所在的位置,此位置的左邊便是此樹的左子樹的中根遍歷的序列,右邊便是此樹的右子樹的中根遍歷序列,用遞歸的思想就可以很簡單的完成此樹的創建,代碼如下:
BtNode * CreateBtTree(char *pre, char *in, int n)
{
BtNode *s =NULL;
if (n > 0)
{
s = BuyBtNode();
s->data = pre[0];
int pos = FindIndex(pre, in,n);
s->leftchild = CreateBtTree(pre + 1, in, pos);
s->rightchild = CreateBtTree(pre + pos + 1, in + pos + 1, n - pos - 1);
}
return s;
}
根據一個先根 序列去創建一個二叉樹,比如此序列:”ABC##DE##F##G#H##”,遇到一個#號就代表遇到了NULL,就不再繼續,開始返回,同樣用遞歸實現,代碼如下:
//這裏必須要使用引用,不然++p只是改變的本函數堆棧的指針
BtNode* CreateBinaryTree(char *&p)
{
if (p == NULL||*p=='#')
return NULL;
BtNode*node = BuyBtNode();
node->data = p[0];
node->leftchild = CreateBinaryTree(++p);
node->rightchild = CreateBinaryTree(++p);
return node;
}
還有很多關於二叉樹創建的方法,都差不多,這裏不再贅述。
二叉樹的遍歷
下面就是關於二叉樹的遍歷的問題,有先根遍歷,中根遍歷,後根遍歷,他們使用的都是遞歸的思想,代碼實現如下:
void InOderBtTree(BtNode*root)
{
if (root == NULL)
return;
InOderBtTree(root->leftchild);
cout << root->data << " ";
InOderBtTree(root->rightchild);
}
void PreOderBtTree(BtNode*root)
{
if (root == NULL)
return;
cout << root->data << " ";
PreOderBtTree(root->leftchild);
PreOderBtTree(root->rightchild);
}
void LastOderBtTree(BtNode*root)
{
if (root == NULL)
return;
LastOderBtTree(root->leftchild);
LastOderBtTree(root->rightchild);
cout << root->data << " ";
}
這裏用的是遞歸的方法實現,下面是使用的是非遞歸的方式實現,但是要藉助棧,代碼如下:
void NicePreOderBtTree(BtNode*root)
{
if (root == NULL)
return;
stack<BtNode*> st;
BtNode*p = root;
while (p != NULL||!st.empty())
{
while (p != NULL)
{
cout << p->data << " ";
st.push(p);
p = p->leftchild;
}
p = st.top();
st.pop();
p = p->rightchild;
}
cout << endl;
}
void NiceInOderBtTree(BtNode *root)
{
if (root == NULL)
return;
stack<BtNode*> st;
BtNode*p = root;
while ( p != NULL || !st.empty())
{
while (p != NULL)
{
st.push(p);
p = p->leftchild;
}
p = st.top();
st.pop();
cout << p->data << " ";
p = p->rightchild;
}
cout << endl;
}
void NiceLastOderBtTree(BtNode*root)
{
if (root == NULL)
return;
stack<BtNode*> st;
BtNode*p = root;
BtNode*tag = NULL;
while (p != NULL || !st.empty())
{
while (p != NULL)
{
st.push(p);
p = p->leftchild;
}
p = st.top();
st.pop();
if (p->rightchild == NULL || tag == p->rightchild)
{
cout << p->data << " ";
tag = p;
p = NULL;
}
else
{
st.push(p);
p = p->rightchild;
}
}
cout << endl;
}
二叉樹的節點個數
計算二叉樹的Size,即二叉樹的節點個數,利用遞歸的思想,節點個數就等於左子樹的節點個數加上右子樹的節點個數加上本身的一個元素,如此重複就形成了遞歸,代碼如下:
int GetSize(BtNode*root)
{
if (root == NULL)
return 0;
return GetSize(root->leftchild) + GetSize(root->rightchild) + 1;
}
二叉樹的深度
二叉樹的深度的計算方法和二叉樹的節點個數的方法很相似,即左子樹和右子樹中最大的深度加一,使用遞歸實現代碼如下:
int GetDepth(BtNode*root)
{
if (root == NULL)
return 0;
int left_depth = GetDepth(root->leftchild);
int right_depth = GetDepth(root->rightchild);
return left_depth > right_depth ? left_depth + 1 : right_depth+1;
}
根據孩子找雙親
遇到一個節點看齊左右孩子是否等於此孩子,若等於就將此節點返回,否則就先遞歸遍歷左孩子,若左孩子沒有找到,就再去遍歷右孩子,如果都沒有找到就返回NULL,遞歸代碼實現如下:
BtNode * FindParent(BtNode *ptr, BtNode *child)
{
if (ptr == NULL || child == NULL || ptr == child)
return NULL;
if (ptr->leftchild == child || ptr->rightchild == child)
return ptr;
BtNode*p = FindParent(ptr->leftchild, child);
if (p == NULL)
{
p = FindParent(ptr->rightchild, child);
}
return p;
}
遍歷第k層
有左孩子右孩子就遍歷其左右孩子,每遍歷一層就k-1,當k==1時就打印,使用遞歸代碼實現如下:
void Print_K_Item(BtNode *p, int k)
{
if (p == NULL || k == 0)
return;
if (k == 1)
cout << p->data << " ";
Print_K_Item(p->leftchild, k - 1);
Print_K_Item(p->rightchild, k - 1);
}
二叉樹的銷燬
二叉樹的銷燬就是二叉樹的後序遍歷,之前是打印,銷燬就是直接free就可以了,代碼實現如下:
void Destory(BtNode*root)
{
if (root == NULL)
return;
Destory(root->leftchild);
Destory(root->rightchild);
free(root);
}
歡迎批評指正!