数据结构与算法之二叉搜索树
與鏈表不同,樹是一種非線性的數(shù)據(jù)結(jié)構(gòu)。樹中最常用的是二叉樹,二叉樹限制了子樹的數(shù)量,也就是每個(gè)結(jié)點(diǎn)的子樹至多2個(gè),并且這兩個(gè)子樹是有順序的。而二叉搜索樹(二叉查找樹,二叉排序樹)是指根節(jié)點(diǎn)的關(guān)鍵字大于左子樹的,而小于右子樹,并且,左右子樹也是一顆二叉搜索樹。也就是說中序遍歷一顆二叉搜索樹,它的輸出是從小到大排序好的。
除了普通的二叉搜索樹之外,還有很多關(guān)于它的變形。
二叉平衡搜索樹,即即是一顆二叉平衡樹,也是一顆搜索樹,平衡樹即任意一個(gè)結(jié)點(diǎn)的左子樹的高度與右子樹的高度之差的絕對(duì)值不大于1。
紅黑樹,也是一種特殊的二叉查找樹,除了具備查找樹的特點(diǎn),它的每個(gè)結(jié)點(diǎn)上還有一個(gè)記錄紅黑顏色的元素。
這里我們主要討論一般的二叉搜索樹。
二叉搜索樹,其實(shí)就是一顆特殊的樹,任何適用于樹的算法都適用于二叉搜索樹。當(dāng)然它也是圖,任何適用于圖的算法也適用于二叉搜索樹。圖中的深度優(yōu)先搜索(DFS)其實(shí)就是樹中的前序遍歷,廣度優(yōu)先搜索(BFS)就是樹中的層序遍歷。當(dāng)然圖中還有很多其他算法也都適用于樹。
1、二叉樹的數(shù)據(jù)結(jié)構(gòu)
typedef struct binSrcTreeNode{int element;struct binSrcTreeNode *pLeft;struct binSrcTreeNode *pRight; }BSTNode;2、動(dòng)態(tài)分配一個(gè)二叉樹的結(jié)點(diǎn)
BSTNode* allocNode(int element){BATNode *pNode = (BSTNode*)malloc(sizeof(BSTNode));if(NULL != pNode){pNode->element = element;pNode->pLeft = NULL;pNode->pRight = NULL;}return pNode; }3、二叉搜索樹的查找
由于二叉搜索樹是已經(jīng)排序了的二叉樹,所以可以通過二分查找來搜索。先判斷是否等于根節(jié)點(diǎn),如果大于根節(jié)點(diǎn)的關(guān)鍵字,搜索右子樹,小于根節(jié)點(diǎn)的關(guān)鍵字,搜索左子樹。
bool searchInBSTree(const BSTNode *pRoot,int element,BSTNode **pNode){if(NULL == pRoot)return false;*pNode = pRoot;if(pRoot->element == element){return true;}else if(pRoot->element > element)return searchInBSTree(pRoot->pLeft,element,pNode);elsereturn searchInBSTree(pRoot->pRight,element,pNode); }4、二叉搜索樹的插入
首先查找二叉樹是是否已經(jīng)存在該元素,如果已經(jīng)存在返回false;如果不存在,插入該結(jié)點(diǎn),插入元素大于根節(jié)點(diǎn),則插入右子樹,否則,插入左子樹中。
5、二叉搜索樹的刪除
二叉搜索樹的刪除分為三種情況:
(1) 刪除結(jié)點(diǎn)為葉子結(jié)點(diǎn),直接刪除該結(jié)點(diǎn),再修改其父結(jié)點(diǎn)的指針(注意分是根結(jié)點(diǎn)和不是根節(jié)點(diǎn))。
(2) 刪除結(jié)點(diǎn)為單支結(jié)點(diǎn)(即只有左子樹或右子樹)。
(3) 刪除結(jié)點(diǎn)的左子樹和右子樹均不空。
bool deleteFromBSTree(BSTNode **pRoot,int element){if(NULL == pRoot || NULL == *pRoot)return false;BSTNode **pSrc = NULL;BSTNode **pParent = NULL;if(searchInBSTree(*pRoot,element,pParent,pSrc)){if(NULL == *pSrc->pLeft && NULL == *pSrc->pRight){free(*pSrc);*pSrc = NULL;return true;}else if(NULL == *pSrc->pLeft){if(*pSrc == *pParent->pLeft)*pParent->pLeft = *pSrc->pRight;else if(*pSrc == *pParent->pRight)*pParent->pRight = *pSrc->pRight;free(*pSrc);return true;}else if(NULL == *pSrc->pRight){if(*pSrc == *pParent->pLeft)*pParent->pLeft = *pSrc->pLeft;else if(*pSrc == *pParent->pRight)*pParent->pRight = *pSrc->pLeft;free(*pSrc);return true;}else{BSTNode *pNode = *pSrc;BSTNode *pChild = *pSrc->pLeft;while(pChild->pRight){pNode = pChild;pChild = pChild->pRight;}if(pNode == *pSrc) pNode->pLeft = pChild->pLeft;else pNode->pRight = pChild->pLeft;if(*pSrc == *pParent->pLeft) *pParent->pLeft = pChild;else *pParent->pRight = pChild;pChild->pLeft = *pSrc->pLeft;pChild->pRight = *pSrc->pRight;return true;}}return false; }6、二叉搜索樹的前序中序后序遍歷
/* preOrder to traverse the binarySearchTree.*/ void preOrderBinarySearchTree(const BSTNode *pRoot){if(NULL == pRoot)return ;printf("%d ",pRoot->element);preOrderBinarySearchTree(pRoot->pLeft);preOrderBinarySearchTree(pRoot->pRight); }/* inOrder to traverse the binarySearchTree.*/ void inOrderBinarySearchTree(const BSTNode *pRoot){if(NULL == pRoot)return ;inOrderBinarySearchTree(pRoot->pLeft);printf("%d ",pRoot->element);inOrderBinarySearchTree(pRoot->pRight); }/* posOrder to traverse the binarySearchTree.*/ void posOrderBinarySearchTree(const BSTNode *pRoot){if(NULL == pRoot)return ;posOrderBinarySearchTree(pRoot->pLeft);posOrderBinarySearchTree(pRoot->pRight);printf("%d ",pRoot->element); }?
7、釋放結(jié)點(diǎn)
void freeBinarySearchTree(BSTNode *pRoot){if(NULL == pRoot)return ;freeBinarySearchTree(pRoot->pLeft);freeBinarySearchTree(pRoot->pRight);free(pRoot); }?
完整代碼詳見:https://github.com/whc2uestc/DataStructure-Algorithm/tree/master/tree
?
轉(zhuǎn)載于:https://www.cnblogs.com/whc-uestc/p/4638349.html
總結(jié)
以上是生活随笔為你收集整理的数据结构与算法之二叉搜索树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 产业资本循环是
- 下一篇: 如何为自己的项目在pycharm中设置d