二叉查找树

来源:互联网 发布:淘宝历史比价网 编辑:程序博客网 时间:2024/06/12 00:36

二叉查找树概述:

查找树是一种数据结构。它支持多种动态集合操作。包括SEARCH,MINIMUM,MAXIMUM,PREDECESSOR,SUCCESSOR,INSERT以及DELETE,它既可以用作字典,也可以用作优先队列(堆)

在二叉查找树上执行的基本操作的时间与树高度成正比。对于一棵含有n个结点的完全二叉树,这些操作的最坏情况运行时间为O(nlgn)。但是,如果树是含有n个结点的线性链,则这些操作的最坏情况运行时间为O(n)(所有结点都插在树的同一边,因此树变成了线性链)。

 

一棵二叉树查找树是按二叉树结构来组织的。这样的树可以用链表结构表示,其中每一个结点就是一个对象。结点中除了key域和卫星数据外,还包含域left,right,p,它们分别指向结点的左儿子,右儿子和父结点(多一个指向父结点的指针,会方便很多,比较找前继和后继结点,非递归无栈中序遍历树等等)。根结点是树中唯一的父结点域为NIL的结点。(非递归无栈中序遍历树可以利用这个作为函数的中止条件)

 

二叉查找树的基本性质:

1、设x为二叉查找树中的一个结点。如果y是x左子树中的一个结点,则key[y] <= key[x]。如果y是x的右子树中的一个结点,则key[x] <= key[y]。

2、遍历一棵含有n个结点的二叉查找树所需时间为O(n)。

 

PS:以上均取自《算法导论》,括号内为自己的见解,可能有误。

 

#include<stdio.h>#include<stdlib.h>/////////////////////////////////////////Data define typedef int DataType ;typedef struct Node {DataType nData ;struct Node *pLeft ;struct Node *pRight ;struct Node *pParent ;} Node ;typedef struct {Node  *pRoot ;//extra Data,for example the sum of the Node } BTree ;/////////////////////////////////////////////////////////////////////////////////Operate Macro#define N 50#define ROOT(T) (T->pRoot) #define KEY(T) (T->nData)  #define LEFT(T) (T->pLeft) #define RIGHT(T) (T->pRight)  #define PARENT(T) (T->pParent)/////////////////////////////////////////////////////////////////////////////////////////////Fuction Declarevoid TreeInsert(BTree* T,Node *pData) ;void RecuTreeInsert(BTree* T,Node *pData) ;Node* SearchInsertNode(Node* pCurNode,Node* pNewNode) ;Node* TreeMiniMum(Node *pNode) ;Node* RecuTreeMiniMum(Node *pNode) ;Node* TreeMaxiMum(Node *pNode) ;Node* RecuTreeMaxiMum(Node *pNode) ;Node* Successor(Node* pNode) ;Node* Predecessor(Node* pNode) ;void InorderTreeWalk(Node* T) ;void IterInorderTreeWalk(Node* T) ;void NoStackInorderTreeWalk(BTree* T) ;Node* TreeSearch(Node* pNode , DataType nKey) ;Node* IterativeTreeSearch(Node* pNode,DataType nKey) ;Node* TreeDelete(BTree* T,Node *pNode) ;void TreeDestroy(BTree *T) ;////////////////////////////////////////////////////////**************************************************************函数名字:main*功能:程序的主函数**************************************************************/int main(void){int i,n ;Node* A[N] ;BTree* T ;freopen("in.txt","r",stdin) ;while(scanf("%d",&n) != EOF){for(i = 0 ; i < n ; ++i){if((A[i] = (Node*)malloc(sizeof(Node))) == NULL){puts("Malloc Error\n") ;return -1 ;}scanf("%d",&(A[i]->nData)) ;}//Create the BTreeif((T = (BTree*)malloc(sizeof(BTree))) == NULL){puts("Malloc Error\n") ;return -1 ;}T->pRoot = NULL ;for(i = 0 ; i < n ; ++i){TreeInsert(T,A[i]) ;}printf("Inorder Walk the Tree(Recursive version):\n") ;InorderTreeWalk(ROOT(T)) ;printf("\n") ;printf("Inorder Walk the Tree(Iterative (using stack) version):\n") ;IterInorderTreeWalk(ROOT(T)) ;printf("\n") ;printf("Inorder Walk the Tree(No Statck version):\n") ;NoStackInorderTreeWalk(T) ;printf("\n") ;do{DataType nNum ;puts("Input a num you want to search,other character to quit:") ;if(scanf("%d",&nNum) != 1){break ;}if(TreeSearch(ROOT(T),nNum) != NULL){printf("The %d is in the Tree\n",nNum) ;}else{printf("The %d isn't in the Tree\n",nNum) ;}}while(1) ;getchar() ;DataType nInsertData ; puts("\nInput the Data that you want to Insert to the Tree(other input to quit):") ;while(scanf("%d",&nInsertData) == 1){Node *pData ;pData = (Node*)malloc(sizeof(Node)) ;pData->nData = nInsertData ;pData->pLeft = NULL ;pData->pRight = NULL ;pData->pParent = NULL ;TreeInsert(T,pData) ;printf("After Insert the %d,Inorder Walk the Tree(Recursive version):\n",pData->nData) ;InorderTreeWalk(ROOT(T)) ;printf("\n") ;printf("After Insert the %d,Inorder Walk the Tree(Iterative (using stack) version):\n",pData->nData) ;IterInorderTreeWalk(ROOT(T)) ;printf("\n") ;printf("After Insert the %d,Inorder Walk the Tree(No stack version)\n",pData->nData) ;NoStackInorderTreeWalk(T) ;printf("\n") ;}getchar() ;printf("Destroy the Tree,and Inorder the Tree:\n") ;TreeDestroy(T) ;printf("\n") ;}return 0 ;}/********************************************************** * 函数名字:TreeDestroy * 函数功能:清空树的所有结点 * 返回值:void**********************************************************/void TreeDestroy(BTree *T) {Node *pTemp = NULL ;Node *pNextNode = TreeMiniMum(ROOT(T))  ;while(pNextNode != NULL){pTemp = Successor(pNextNode) ;free(pNextNode) ;pNextNode = pTemp ;}T->pRoot = NULL ;}/******************************************************* * 函数名称:IterInorderTreeWalk * 函数功能:中序遍历二叉查找树,使用栈结构 * 返回值:void  *****************************************************/void IterInorderTreeWalk(Node* T) {Node* NodeStack[N] ;int sp = 0 ;Node* pNode = T;if(pNode != NULL){NodeStack[sp++] = pNode ; //push pwhile(sp > 0){pNode = LEFT(pNode) ;while(pNode != NULL){NodeStack[sp++] = pNode ;pNode = LEFT(pNode) ;}do{sp-- ;pNode = NodeStack[sp] ;printf("%-3d",pNode->nData) ;pNode = RIGHT(pNode) ;}while(NULL == pNode && sp > 0) ;if(pNode != NULL){NodeStack[sp++] = pNode ;}}}}/***************************************************** * 函数名称:TreeDelete * 函数功能:删除树中指定结点 * 返回值:指向被删除结点的指针 * 备注:未测试  ****************************************************/Node* TreeDelete(BTree* T,Node *pNode) {Node *pDeleteNode = NULL ;Node *pChildNode = NULL ;Node TempData ;if(NULL == LEFT(pNode) || NULL == RIGHT(pNode)){pDeleteNode = pNode ;}else{pDeleteNode = Successor(pNode) ;}if(LEFT(pNode) != NULL){pChildNode = LEFT(pNode) ;}else{pChildNode = RIGHT(pNode) ;}if(pChildNode != NULL){pChildNode->pParent = PARENT(pDeleteNode) ;}if(NULL == PARENT(pDeleteNode)){T->pRoot = pChildNode ;}else if(pDeleteNode == LEFT((pDeleteNode->pParent))){LEFT(PARENT(pDeleteNode)) = pChildNode ;}else{RIGHT(PARENT(pDeleteNode)) = pChildNode ;}if(pDeleteNode != pNode){pNode->nData = KEY(pDeleteNode) ;//extra data}return pDeleteNode ;}/*******************************************************  * 函数名称:TreeSearch  * 函数功能:在二叉树中查找指定键值的结点(返回找到的第一个结点)  * 返回值:指向指定键值的结点的指针  ******************************************************/Node* TreeSearch(Node* pNode ,int nKey) {if(NULL == pNode || KEY(pNode) == nKey){return pNode ;}else if(nKey < KEY(pNode)){return TreeSearch(LEFT(pNode),nKey) ;}else{return TreeSearch(RIGHT(pNode),nKey) ;}}/******************************************************* * 函数名称:IterativeTreeSearch (非递归版) * 函数功能:在二叉树中查找指定键值的结点(返回找到的第一个结点) * 返回值: 指向指定键值的结点的指针 *******************************************************/Node* IterativeTreeSearch(Node* pNode,DataType nKey) {while(pNode != NULL && KEY(pNode) != nKey){if(nKey < KEY(pNode)){pNode = LEFT(pNode) ;}else{pNode = RIGHT(pNode) ;}}return pNode ;}/******************************************************* * 函数名称:NoStackInorderTreeWalk(非递归无栈版)  * 函数功能:中序遍历二叉树 * 返回值:无 *******************************************************/void NoStackInorderTreeWalk(BTree* T) {Node *pNextNode = NULL ;pNextNode = TreeMiniMum(ROOT(T)) ;while(pNextNode != NULL){printf("%-3d",pNextNode->nData) ;pNextNode = Successor(pNextNode) ;}}/****************************************************** * 函数名称:InorderTreeWalk (递归版) * 函数功能:中序遍历二叉树 * 返回值:无 * ****************************************************/void InorderTreeWalk(Node *pNode) {if(pNode != NULL){InorderTreeWalk(LEFT(pNode)) ;printf("%-3d",KEY(pNode)) ;InorderTreeWalk(RIGHT(pNode)) ;}}/**************************************************** * 函数名称:TreeMaxiMum * 函数功能:返回二叉树的最大值 * 返回值:指向二叉树中最大值结点的指针 ****************************************************/Node* TreeMaxiMum(Node *pNode) {while(RIGHT(pNode) != NULL){pNode = RIGHT(pNode) ;}return pNode ;}/****************************************************** * 函数名称:RecuTreeMaxiMum * 函数功能:返回二叉树的最大值(递归版) ******************************************************/Node* RecuTreeMaxiMum(Node *pNode) {if(RIGHT(pNode) != NULL ){return RecuTreeMaxiMum(RIGHT(pNode)) ;}else{return pNode ;}}/***************************************************** * 函数名称:Successor * 函数功能:返回指向指定结点的后继结点指针 * ***************************************************/Node* Successor(Node* pNode) {Node *pParent ;if(RIGHT(pNode) != NULL){return TreeMiniMum(RIGHT(pNode)) ; //replace recu}pParent = PARENT(pNode) ;while(pParent != NULL && RIGHT(pParent) == pNode){pNode = pParent ;pParent = PARENT(pParent) ;}return pParent ;}/********************************************************** * 函数名称:Predecessor * 函数功能:返回指定结点的后继结点 * 备注:未测试 * ********************************************************/Node* Predecessor(Node* pNode){Node *pParent ;if(LEFT(pNode) != NULL){return TreeMiniMum(LEFT(pNode)) ;}pParent = PARENT(pNode) ;while(pParent != NULL && pNode == LEFT(pParent)){pNode = pParent ;pParent = PARENT(pParent) ;}return pParent ;}/*************************************************** * 函数名称:RecuTreeMiniMum(递归版) * 函数功能:返回二叉树中的最小值 * 备注:未测试 * *************************************************/Node* RecuTreeMiniMum(Node *pNode) {if(LEFT(pNode) != NULL){return RecuTreeMiniMum(LEFT(pNode)) ;}else{return pNode ;}}/*************************************************** * 函数名称:TreeMiniMum * 函数功能:返回二叉树中的最小值  * *************************************************/Node* TreeMiniMum(Node *pNode) {while(LEFT(pNode) != NULL){pNode = LEFT(pNode) ;}return pNode ;}/******************************************************** * 函数名称:SearchInsertNode * 函数功能:寻找插入新结点的父结点 * ******************************************************/Node* SearchInsertNode(Node* pCurNode,Node* pNewNode) {if(NULL == pCurNode){return PARENT(pCurNode) ;}else if(KEY(pNewNode) < KEY(pCurNode)){return SearchInsertNode(LEFT(pCurNode),pNewNode) ;}else{return SearchInsertNode(RIGHT(pCurNode),pNewNode) ;}}/*************************************************** * 函数名称:RecuTreeInsert(递归版) * 函数功能:插入新结点 * 备注:未测试 * *************************************************/void RecuTreeInsert(BTree* T,Node *pData){Node *pParent = NULL ;Node* pCurNode = ROOT(T) ;if(pCurNode != NULL){if(KEY(pData) < KEY(pCurNode)){pParent = SearchInsertNode(LEFT(pCurNode),pData) ;}else{pParent = SearchInsertNode(RIGHT(pCurNode),pData) ;}}pData->pParent = pParent ; if(NULL == pParent){T->pRoot = pData ;}else if(KEY(pData) < KEY(pParent)){pParent->pLeft = pData ;}else {pParent->pRight = pData ;}}/********************************************************8 * 函数名称:TreeInsert * 函数功能:插入新结点 *********************************************************/void TreeInsert(BTree* T,Node *pNode) {Node *pParent ;Node *pCurNode = ROOT(T) ;while(pCurNode != NULL){pParent = pCurNode ;if(KEY(pNode) < KEY(pCurNode)){pCurNode = LEFT(pCurNode) ;}else{pCurNode = RIGHT(pCurNode) ;}}pNode->pParent = pParent ;  if(NULL == pParent){T->pRoot = pNode ;}else if(KEY(pNode) < KEY(pParent)){pParent->pLeft = pNode ;}else{pParent->pRight = pNode ;}}


 

 

原创粉丝点击