資料結構 排序二叉樹(BST) 插入刪除查詢 中序遍歷 銷燬(後序遍歷)
結構概念如下:
排序二叉樹(BST)的優點在於進行資料查詢比較方便,因為他是按照資料來到的順序進行如上的規則進行的
建樹,只要如上的規則進行查詢就能找到需要的資料。但是其缺點也是顯而易見,樹的深度是不可控制的
而且可能極不均勻,考慮 1 2 3 4 5 6 7,這樣的資料建樹全部節點都在左子樹上,級不均勻。那麼給
搜尋資料的效能帶來的較大的影響,所以引入了AVL樹平衡二叉樹,這個在後面再說
關於排序二叉樹BST的各種操作都使用了遞迴演算法,給出遞迴演算法一張我認為很好的圖:
這張圖實際體現了遞迴的真諦 順序呼叫反向返回,這個列子和圖來自小甲魚C視訊也可能來自大話資料結構
上面的程式碼實際上是:
void print()
{
char a;
scanf("%c",&a);
if(a!='#') print();
if(a!='#') printf("%c",a);
}
關於遞迴的經典 費布那切數列和漢諾塔等都可以瞭解一下;
下面迴歸正題,直接給出程式碼和測試用例。說明程式碼大部分來自大話資料結構,銷燬和中序遍歷是我自己寫的,但是我自己進行了理解。
主要刪除資料比較難,分為3種情況
1、刪除節點的左子樹為空,更改*p = (*p)->rchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個右孩子
2、刪除節點的右子樹為空,同理更改*p = (*p)->lchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個左孩子
3、刪除節點左右子樹都不為空,需要進行找到直接前驅或者直接後繼節點進行資料代替。這個就比較複雜直接看程式碼吧
分別進行討論。
其他操作相對簡單不用再秒素就是遞迴,但是需要注意排序返回資料是用中序遍歷,銷燬樹用的是後序遍歷。
程式碼如下:
結構如下:
Create Tree with key:10
Insert Key To Tree(right):20
Insert Key To Tree(right):40
Insert Key To Tree(left):5
Insert Key To Tree(left):1
Insert Key To Tree(left):-1
Insert Key To Tree(left):-20
Insert Key To Tree(right):100
Use inorder traversal method:
-20
-1
1
5
10
20
40
100
no delete data 30 find
........
delete data :10
........
Use inorder traversal method:
-20
-1
1
5
20
40
100
Use postorder traversal method destroy Bst:
Delete node for Key-20
Delete node for Key-1
Delete node for Key1
Delete node for Key100
Delete node for Key40
Delete node for Key20
Delete node for Key5
這裡首先演示了建樹,然後演示了中序遍歷返回有序的結果,然後刪除一個不包含的資料30,
然後刪除一個包含的資料10,然後再次進行中序遍歷,最後使用後續遍歷刪除。
可以看到結果如我們希望的。
二叉排序樹(binary sort tree):
1、也叫做二叉查詢樹
2、如果他的左子樹不為空,則左子樹上所有結點的
值均小於他的根結構的值
3、如果他的右子樹不為空,則右子樹上所有結點的
值均大於他的根結構的值
4、他的左右子樹分別為二叉排序樹
5、按照二叉樹中序遍歷其返回結果樹有序的
下面就是一顆典型的二叉樹,只是是字母,可以將字母換位字母的順序進行審視,但是它不是平衡二叉樹
排序二叉樹(BST)的優點在於進行資料查詢比較方便,因為他是按照資料來到的順序進行如上的規則進行的
建樹,只要如上的規則進行查詢就能找到需要的資料。但是其缺點也是顯而易見,樹的深度是不可控制的
而且可能極不均勻,考慮 1 2 3 4 5 6 7,這樣的資料建樹全部節點都在左子樹上,級不均勻。那麼給
搜尋資料的效能帶來的較大的影響,所以引入了AVL樹平衡二叉樹,這個在後面再說
關於排序二叉樹BST的各種操作都使用了遞迴演算法,給出遞迴演算法一張我認為很好的圖:
這張圖實際體現了遞迴的真諦 順序呼叫反向返回,這個列子和圖來自小甲魚C視訊也可能來自大話資料結構
上面的程式碼實際上是:
void print()
{
char a;
scanf("%c",&a);
if(a!='#') print();
if(a!='#') printf("%c",a);
}
關於遞迴的經典 費布那切數列和漢諾塔等都可以瞭解一下;
下面迴歸正題,直接給出程式碼和測試用例。說明程式碼大部分來自大話資料結構,銷燬和中序遍歷是我自己寫的,但是我自己進行了理解。
主要刪除資料比較難,分為3種情況
1、刪除節點的左子樹為空,更改*p = (*p)->rchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個右孩子
2、刪除節點的右子樹為空,同理更改*p = (*p)->lchild;注意這裡的*p代表的是parent->child,所以這樣做就是將父節原來指向刪除節點的指標,指向刪除節點的下一個左孩子
3、刪除節點左右子樹都不為空,需要進行找到直接前驅或者直接後繼節點進行資料代替。這個就比較複雜直接看程式碼吧
分別進行討論。
其他操作相對簡單不用再秒素就是遞迴,但是需要注意排序返回資料是用中序遍歷,銷燬樹用的是後序遍歷。
程式碼如下:
點選(此處)摺疊或開啟
-
標頭檔案
-
bstort.h
-
#include<stdio.h>
-
typedef int bool;
-
#define false 0
-
#define true 1
-
#define xfree(x) free(x); x = NULL;
-
-
typedef struct BiTnode
-
{
-
int data;
-
struct BiTnode *lchild,*rchild;
-
} BiTnode,*BiTree;
-
-
-
bool SearchBst(BiTree T,int key,BiTree *f,BiTree *p);
-
bool InsertBst(BiTree *T,int key) ;
-
void Inordervist(const BiTree T);
-
void BTreedestroy(BiTree tree);
-
bool DeleteBst(BiTree *T,int key);
- bool Delete(BiTree *p);
點選(此處)摺疊或開啟
-
實現程式
-
bstort.c
-
#include<stdio.h>
-
#include<stdlib.h>
-
#include"bstort.h"
-
/*
-
T = Bst root node
-
key = search key
-
f = T's parent node,used if search failed save last search node pointer
-
if search failed last T is NULL,inital vlaues is NULL,
-
is sucuess f is pointer to p's parent poniter,
-
p = if sucess p is pointer to find node pointer,if failed is pointer to last
-
search node pointer
-
-
*/
-
-
bool SearchBst(BiTree T,int key,BiTree *f,BiTree *p)
-
{
-
if(!T)
-
{
-
*p = *f;
-
return false;
-
}
-
else if(key == T->data)
-
{
-
*p = T;
-
return true;
-
}
-
else if(key < T->data)
-
{
-
*f = T;
-
return SearchBst(T->lchild,key,f,p);
-
}
-
else
-
{
-
*f = T;
-
return SearchBst(T->rchild,key,f,p);
-
}
-
}
-
-
/*
-
T = Bst root node
-
key = key to insert
-
*/
-
bool InsertBst(BiTree *T,int key)
-
{
-
BiTree p = NULL ,s = NULL ,f=NULL;
-
if(!SearchBst(*T,key,&f,&p)) //init NULL,KEY,NULL,&P=NULL
-
{
-
s = (BiTree)calloc(1,sizeof(BiTnode));
-
s->data =key;
-
s->lchild = s->rchild = NULL;
-
-
if(!p)
-
{
-
printf("Create Tree with key:%d\n",key);
-
*T = s; //create Bst one node
-
}
-
else if(key < p->data)
-
{
-
printf("Insert Key To Tree(left):%d\n",key);
-
p->lchild = s;
-
}
-
else
-
{
-
printf("Insert Key To Tree(right):%d\n",key);
-
p->rchild = s;
-
}
-
return true;
-
}
-
else
-
{
-
return false;
-
}
-
}
-
/*
-
inorder traversal method
-
*/
-
-
void Inordervist(const BiTree T)
-
{
-
if(T)
-
{
-
Inordervist(T->lchild);
-
printf("%d\n",T->data);
-
Inordervist(T->rchild);
-
}
-
}
-
-
/*
-
postorder traversal method to destroy tree
-
*/
-
-
void BTreedestroy(BiTree T)
-
{
-
-
if(T)
-
{
-
BTreedestroy(T->lchild);
-
BTreedestroy(T->rchild);
-
printf("Delete node for Key%d\n",T->data);
-
xfree(T);
-
}
-
}
-
-
-
bool DeleteBst(BiTree *T,int key)//use **p *p is parent->child,here is very import
-
{
-
if(!*T)//
-
{
-
printf("no delete data %d find\n........\n",key);
-
return true;
-
}
-
else
-
{
-
if(key == (*T)->data)
-
{
-
return Delete(T);
-
}
-
else if(key < (*T)->data)
-
{
-
return DeleteBst(&(*T)->lchild,key);//here use lchild pointer's address
-
}
-
else
-
{
-
return DeleteBst(&(*T)->rchild,key);
-
}
-
}
-
}
-
-
bool Delete(BiTree *p)//use **p *p is parent->child,here is very import
-
{
-
BiTree q,s;
-
-
printf("delete data :%d\n........\n",(*p)->data);
-
if((*p)->rchild == NULL)//right node is NULL
-
{
-
q = *p;
-
*p = (*p)->lchild;
-
xfree(q);
-
}
-
else if((*p)->lchild ==NULL)//leaf node is NULL
-
{
-
q = *p;
-
*p = (*p)->rchild;
-
xfree(q);
-
}
-
else //exp:use ...20 30 50 (60 delete)... use 50 replace 60 ,use replace not free find node
-
{
-
q = *p;
-
//---------------
-
s = (*p)->lchild;
-
while(s->rchild) //if s->rchild is NULL q=*p mean (*p)->lchild s have no right node
-
{
-
q = s;
-
s = s->rchild;
-
}
-
(*p)->data = s->data;
-
-
/*-------------- here find near delete node small data,frist find lchild then find
-
all small data root node then find last right node this is require data*/
-
-
if(q!=*p) //if (*p)->lchild s have right node
-
{
-
q->rchild =s->lchild;
-
}
-
else // if (*p)->lchild s have no right node
-
{
-
q->lchild = s ->lchild;
-
}
-
xfree(s);//free find last right node,beacuse it's data used for find node
-
}
- }
點選(此處)摺疊或開啟
-
測試用例和主函式
-
main.c
-
#include<stdio.h>
-
#include"bstort.h"
-
-
-
int main(void)
-
{
-
BiTree root = NULL;
-
InsertBst(&root,10);
-
InsertBst(&root,20);
-
InsertBst(&root,40);
-
InsertBst(&root,5);
-
InsertBst(&root,1);
-
InsertBst(&root,-1);
-
InsertBst(&root,-20);
-
InsertBst(&root,100);
-
printf("Use inorder traversal method:\n");
-
Inordervist(root);
-
DeleteBst(&root,30);
-
DeleteBst(&root,10);
-
printf("Use inorder traversal method:\n");
-
Inordervist(root);
-
printf("Use postorder traversal method destroy Bst:\n");
-
BTreedestroy(root);
- }
結構如下:
Create Tree with key:10
Insert Key To Tree(right):20
Insert Key To Tree(right):40
Insert Key To Tree(left):5
Insert Key To Tree(left):1
Insert Key To Tree(left):-1
Insert Key To Tree(left):-20
Insert Key To Tree(right):100
Use inorder traversal method:
-20
-1
1
5
10
20
40
100
no delete data 30 find
........
delete data :10
........
Use inorder traversal method:
-20
-1
1
5
20
40
100
Use postorder traversal method destroy Bst:
Delete node for Key-20
Delete node for Key-1
Delete node for Key1
Delete node for Key100
Delete node for Key40
Delete node for Key20
Delete node for Key5
這裡首先演示了建樹,然後演示了中序遍歷返回有序的結果,然後刪除一個不包含的資料30,
然後刪除一個包含的資料10,然後再次進行中序遍歷,最後使用後續遍歷刪除。
可以看到結果如我們希望的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2127320/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 二叉樹--後序遍歷二叉樹
- 二叉樹(BST)中序遍歷的三種方法二叉樹
- 從中序與後序遍歷序列構造二叉樹二叉樹
- 二叉樹的前序,中序,後序遍歷方法總結二叉樹
- 二叉樹中序和後序遍歷表示式二叉樹
- 144.二叉樹的前序遍歷145.二叉樹的後序遍歷 94.二叉樹的中序遍歷二叉樹
- 【資料結構與演算法】二叉樹的 Morris 遍歷(前序、中序、後序)資料結構演算法二叉樹
- 二叉樹的先中後序遍歷二叉樹
- 二叉樹的先,中,後序遍歷二叉樹
- 二叉樹的前中後序遍歷二叉樹
- 雙向迴圈連結串列:(建立、插入、遍歷、求長、查詢、刪除、排序、銷燬)待測排序
- 二叉樹的前序、中序、後序三種遍歷二叉樹
- 二叉樹的四種遍歷方法:先序,中序,後序,層序二叉樹
- 根據前序遍歷序列、中序遍歷序列,重建二叉樹二叉樹
- [資料結構]二叉樹的前中後序遍歷(遞迴+迭代實現)資料結構二叉樹遞迴
- 【Algorithm&DataStructure】二叉查詢樹(BST)的遍歷GoASTStruct
- LeetCode-106-從中序與後序遍歷序列構造二叉樹LeetCode二叉樹
- 388,先序遍歷構造二叉樹二叉樹
- [資料結構] 根據前中後序遍歷中的兩種構造二叉樹資料結構二叉樹
- 二叉樹的層序遍歷二叉樹
- python-二叉樹:前、中、後、層序遍歷Python二叉樹
- 演算法 -- 實現二叉樹先序,中序和後序遍歷演算法二叉樹
- 根據二叉樹的前序遍歷和中序遍歷輸出二叉樹;二叉樹
- 二叉樹排序樹的建立,遍歷和刪除二叉樹排序
- 二叉搜尋樹的後序遍歷序列
- 資料結構 二叉樹遍歷資料結構二叉樹
- 二叉樹遍歷順序與方法小結二叉樹
- 144. 二叉樹的遍歷「前序、中序、後序」 Golang實現二叉樹Golang
- ast 後序遍歷AST
- 中序線索二叉樹的構造和遍歷二叉樹
- 二叉樹:構造二叉樹(通過前序和中序遍歷)、映象翻轉、層次遍歷二叉樹
- 遞迴和迭代實現二叉樹先序、中序、後序和層序遍歷遞迴二叉樹
- 刷題筆記:樹的前序、中序、後序遍歷筆記
- 刷題系列 - 中序和後序遍歷佇列,構造對應二叉樹;佇列二叉樹
- 106. 從中序與後序遍歷序列構造二叉樹——Java實現二叉樹Java
- Leetcode——94.二叉樹的中序遍歷LeetCode二叉樹
- 94. 二叉樹的中序遍歷(迭代)二叉樹
- LeeCode-94. 二叉樹的中序遍歷二叉樹
- L2_006樹的遍歷(後序+中序->前序/層序)