二叉樹創建(層序)
與層序有關的要用到隊列,因此創建一個隊列
Bintree creat()//二叉樹層序創建(想用C++STL庫的,到時候改成new)
{
int data;
BinTree BT,T;
scanf("%d",&data);
if(data!=0)
{
BT=(BinTree)malloc(sizeof(struct TNode));
BT->data=data;
BT->left=NULL;
BT->right=NULL;
q.push(data);
}
else return NULL;
while(!q.empty())
{
T=q.front();
scanf("%d",&data);
if(data==0) T->left=NULL;
else{
T->left=(BinTree)malloc(sizeof(struct TNode));
T->left->data=data;
q.push(T->left)
}
scanf("%d",&data);
if(data==0) T->right=NULL;
else{
T->right=(BinTree)malloc(sizeof(struct TNode));
T->right->data=data;
q.push(T->right)
}
}
return BT;
}
輸出二叉樹中所有葉結點
分析:用到的知識是二叉樹的遍歷,在遍歷的時候加條件(左子樹和右子樹都爲空即可)
void Preorderprintleaves(BinTree BT)
{
if(BT)
{
if(!BT->left&&!BT->right)
{
printf("%d",BT->data);
}
Preorderprintleaves(BT->left);
Preorderprintleaves(BT->right);
}
}
遞歸求二叉樹高度
分析:求二叉樹高度=求左子樹高度和求右子樹高度中最大的那個=…=…(遞推下去吧)
int getHeight(BinTree BT)
{
int HL,HR,MAXH;
if(BT)
{
HL=getHeight(BT->left);
HR=getHeight(BT->right);
MAXH=HL>HR?HL:HR;
return(MAXH+1);
}
else return 0;/*空樹高度爲0*/
}
二叉搜索樹(BST)的查找
注意返回的還是指針,指向二叉樹的結點
如果發現BST爲空了(查完了還沒找到) 返回查找失敗
typedef struct node *Bintree;
struct node{
int data;
Bintree left,right;
};
Bintree find(Bintree BST,int x)
{
if(!BST) return NULL;
else
{
if(BST->data==x) return BST;//返回當前結點的地址
else if(BST->data>x) return find(BST->left,x);
else if(BST->data<x) return find(BST->right,x);
}
}
查找BST的最大最小值
方法一:遞歸
方法二:迭代
利用BST的性質,最小元素一定在樹的最左分支的端結點上
Bintree FindMax(Bintree BST)
{
if(!BST) return NULL;
else if(BST->right==NULL) return BST;
else return FindMax(BST->right);
}
Bintree findmin(Bintree BST)
{
if(BST)
{
while(BST->left)
{
BST=BST->left;
}
return BST;
}
}
BST的插入
操作類似於查找,必須記得分情況
原樹爲空,那麼建一個只有一個結點的樹
原樹不爲空,遞歸尋找插入的位置
最後返回的也是指針,指向插入元素的位置
(遞歸真是個好東西啊)
Bintree insert(Bintree BST,int x)
{
if(!BST)
{
BST=(Bintree)malloc(sizeof(struct node));
BST->data=x;
BST->left=BST->right=NULL;
}
else
{
if(BST->data>x)
{
insert(BST->left,x);
}
else if (BST->data<x)
{
insert(BST->right,x);
}
}
return BST;
}
二叉搜索樹的插入其實還是很方便的,因爲數據的插入後一定接在樹下方,不影響其他結點,但是刪除就相對複雜了,一個結點的刪除會影響其他結點的位置
二叉搜索樹的刪除
三種情況
1.刪除的是葉結點
2.刪除的結點只有一個孩子結點
3.刪除的結點有左右兩顆子樹,那麼要轉換爲第二種情況:選取左子樹中的最大元素或者右子樹的最小元素(利用上面講的findmax和findmin函數鴨)
Bintree delete(Bintree BST,int x)
{
//先找到要被刪除的元素
Bintree tmp;
if(!BST) return printf("未找到");
else
{
if(x<BST->data) delete(BST->left,x);
else if(x>BST->data) delete(BST->right,x);
else if(x==BST->data)
{
if(BST->left&&BST->right)
/*有兩個子節點*/
{
tmp=findmin(BST->right);
BST->data=tmp->data;
/*重要過程?遞歸(why?如何理解?)*/
BST->right=delete(BST->right,BST->data);
}
else
{
tmp=BST;
if(!BST->left)//只有右孩子
BST=BST->right;
else
{
BST=BST->left;
}
free(tmp);//原來數據被刪除,指針改變方向
}
}
return BST;
}
}
//最後返回值還是指針,指向的是刪除後的結點,原來的數據不復存在