二叉樹對我們來說已經不陌生了,這是一個非常常用的數據結構,常見的二叉樹的應用:二叉排序樹、二叉平衡樹、紅黑樹、二叉堆等等,這些都是關於二叉樹的一些數據結構;好了我們廢話少說,下面我們一起來了解一些二叉樹。
二叉樹的一些基本術語和特性
二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left
subtree)和“右子樹”(right subtree)。
二叉樹的每個結點至多隻有二棵子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,次序不能顛倒。二叉樹的第i層至多有個結點;深度爲k的二叉樹至多有個結點;對任何一棵二叉樹T,如果其終端結點數爲,度爲2的結點數爲,則。
滿二叉樹:一棵深度爲k,且有(2的k次方)-1個節點成爲滿二叉樹。
完全二叉樹:深度爲k,有n個節點的二叉樹,當且僅當其每一個節點都與深度爲k的滿二叉樹中序號爲1至n的節點對應時,稱之爲完全二叉樹。
二叉樹的存儲結構:
順序存儲表示
二叉樹可以用數組或線性表來存儲,而且如果這是完全二叉樹,這種方法不會浪費空間。用這種緊湊排列,如果一個結點的索引爲i,它的子結點能在索引2i+1和2i+2找到,並且它的父節點(如果有)能在索引floor((i-1)/2)找到(假設根節點的索引爲0)。這種方法更有利於緊湊存儲和更好的訪問的局部性,特別是在前序遍歷中。然而,它需要連續的存儲空間,這樣在存儲高度爲h的n個結點組成的一般普通樹時將會浪費很多空間。一種最極壞的情況下如果深度爲h的二叉樹每個節點只有右孩子需要佔用2的h次冪減1,而實際卻只有h個結點,空間的浪費太大,這是順序存儲結構的一大缺點。
二叉鏈表存儲表示
在使用記錄或內存地址指針的編程語言中,二叉樹通常用樹結點結構來存儲。有時也包含指向唯一的父節點的指針。如果一個結點的子結點個數小於2,一些子結點指針可能爲空值,或者爲特殊的哨兵結點。 使用鏈表能避免順序儲存浪費空間的問題,算法和結構相對簡單,但使用二叉鏈表,由於缺乏父鏈的指引,在找回父節點時需要重新掃描樹得知父節點的節點地址。
typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; /* 左右孩子指針 */ }BiTNode,*BiTree;
二叉樹的基本操作
/* 按先序次序輸入二叉樹節點的值(可爲字符型或整型,在主程中定義),*/
/* 構造二叉鏈表表示的二叉樹T。變量Nil表示空(子)樹。 */
void CreateBiTree(BiTree &T)
{
TElemType ch;
scanf(form, ch);
if(ch == Nil) /* 空 */
T = NULL;
else
{
T = new BiTNode; /* 生成根結點*/
if(NULL == T)
exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild); /* 構造左子樹*/
CreateBiTree(T->rchild); /* 構造右子樹*/
}
}
/*二叉樹的先、中、後序遍歷*/
void preOrder(BiTree root)
{
if( root != NULL)
{
cout << root->data << ' ';
preOrder(root->lchild);
preOrder(root->rchild);
}
}
void inOrder(BiTree root)
{
if( root != NULL)
{
preOrder(root->lchild);
cout << root->data << ' ';
preOrder(root->rchild);
}
}
void postOrder(BiTree root)
{
if( root != NULL)
{
preOrder(root->lchild);
preOrder(root->rchild);
cout << root->data << ' ';
}
}
/*求二叉樹的深度*/
int getDepth(BiTree root)
{
int deplef = 0;
int deprig = 0;
int deptal = 0;
if(root == NULL) return 0;
deplef = getDepth(root->lchild) + 1;
deprig = getDepth(root->rchild) + 1;
deptal = deplef > deprig ? deplef:deprig;
return deptal;
}
/*求二叉樹的葉子結點個數*/
int CountTreeLeaf(BiTree root)
{
if(root == NULL)
return 0;
else if(root->lchild == NULL && root->rchild == NULL)
return 1;
else
return CountTreeLeaf(root->lchild)+CountTreeLeaf(root->rchild);
}
待續。。。。。