日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用C语言实现二叉搜索树的遍历、查找、插入、删除

發(fā)布時間:2024/3/7 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用C语言实现二叉搜索树的遍历、查找、插入、删除 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

IDE:codebloks,編譯器:gcc5.1.0
二叉搜索樹和我們通常的二叉樹還是有一定的區(qū)別,顧名思義,一顆二叉搜索樹以一顆二叉樹來組織,其中每一個結(jié)點就是一個對象。除了key(關(guān)鍵字)和衛(wèi)星數(shù)據(jù)外,每個節(jié)點還包括left(左孩子指針)、right(右孩子指針)和p。如果孩子結(jié)點不存在則為NULL。
二叉搜索樹的性質(zhì)如下:
設(shè)x是二叉搜索樹中的一個結(jié)點。如果y是x的左子樹中的一個結(jié)點,那么y.key≤x.key。如果y是x右子樹中的一個結(jié)點,那么y.key≥x.key。圖a和b正好說明了這一點。

二叉搜索樹的遍歷有三種,分別為先序遍歷(perorder tree walk)、中序遍歷(inorder tree walk)、后續(xù)遍歷(postorder tree walk)。
1.首選定義二叉搜索樹結(jié)點的數(shù)據(jù)結(jié)構(gòu),為了簡單期間,只定義了關(guān)鍵字,左孩子和右孩子指針本例子中的二叉搜索樹如圖c所示:

#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <stdbool.h> //binary search tree struct BSTNode {int data;struct BSTNode *pLchild;struct BSTNode *pRchild;struct BSTNode *pParent; };

2.下面分別是三種遍歷的C語言實現(xiàn)。唯一不同的地方是輸出關(guān)鍵字的位置不void PreTraverseBSTree(pBstNode pBST)

void PreTraverseBSTree(struct BSTNode *pBST) {if(NULL != pBST){printf("數(shù)據(jù)為:%d,父節(jié)點地址為:%p\n",pBST ->data,pBST ->pParent);if(NULL != pBST ->pLchild )PreTraverseBSTree(pBST ->pLchild);if(NULL != pBST ->pRchild)PreTraverseBSTree(pBST ->pRchild);} }void InTraverseBSTree(struct BSTNode *pBST) {if(NULL != pBST){if(NULL != pBST ->pLchild )PreTraverseBSTree(pBST ->pLchild);printf("數(shù)據(jù)為:%d,父節(jié)點地址為:%p\n",pBST ->data,pBST ->pParent);if(NULL != pBST ->pRchild)PreTraverseBSTree(pBST ->pRchild);} }void PostTraverseBSTree(struct BSTNode *pBST) {if(NULL != pBST){if(NULL != pBST ->pLchild )PreTraverseBSTree(pBST ->pLchild);if(NULL != pBST ->pRchild)PreTraverseBSTree(pBST ->pRchild);printf("數(shù)據(jù)為:%d,父節(jié)點地址為:%p\n",pBST ->data,pBST ->pParent);} }

3.下面是查找的C語言實現(xiàn)。第一個版本是自己實現(xiàn)的,在寫的過程中,想到了是不是可以去掉return,去掉return編譯器報警,經(jīng)過一番查找資料和思考,發(fā)現(xiàn)有沒有return不會影響結(jié)果,報警的原因是SearchBSTree()的返回值類型是pBstNode,如果去掉return就沒有返回值,類型不匹配就會報警。版本1沒有版本2效率高,版本2沒有版本3效率高,版本2和版本3參考自《算法導論》。版本3采用了while循環(huán)展開遞歸,用一種迭代方式重寫這個過程。對于大多數(shù)計算機,迭代版本的效率要高很多。

//查找成功返回該結(jié)點的地址,失敗返回NULL struct BSTNode *SearchBSTree(struct BSTNode *pBST,int key) //版本1 {if(NULL == pBST)return NULL;else if(key < pBST ->data)return SearchBSTree(pBST ->pLchild,key);else if(key > pBST ->data)return SearchBSTree(pBST ->pRchild,key);else return pBST; }struct BSTNode *SearchBSTree(struct BSTNode *pBST,int key) //版本2 {if(NULL == pBST || key == pBST ->data)return pBST;else if(key < pBST ->data)return SearchBSTree(pBST ->pLchild,key);else return SearchBSTree(pBST ->pRchild,key); }struct BSTNode *SearchBSTree(struct BSTNode *pBST,int key) //版本3 {while(NULL != pBST && key != pBST ->data){if(key < pBST ->data)pBST = pBST ->pLchild;else pBST = pBST ->pRchild;}return pBST; }

4.在二叉搜索樹中尋找最大值和最小值。由二叉搜索樹的性質(zhì)可知,我們總能在二叉搜索樹中找到一個元素,兩個擁有相同父結(jié)點的子結(jié)點中,左結(jié)子點的值肯定小于父節(jié)點,也小于右子結(jié)點,所以最小值總在二叉搜索樹的左子樹中,最大值總在右子樹中。實現(xiàn)的代碼如下:時間復雜度為O(h)。

struct BSTNode *SearchMinBSTree(struct BSTNode *pBST,int *pMinData)//查找二叉搜索樹中最小的值 {while(NULL != pBST ->pLchild){pBST = pBST ->pLchild;}*pMinData = pBST ->data;return pBST; } struct BSTNode *SearchMaxBSTree(struct BSTNode *pBST,int *pMaxData) //查找二叉搜索樹中最大的值 {while(NULL != pBST ->pRchild){pBST = pBST ->pRchild;}*pMaxData = pBST ->data;return pBST; }

5.向二叉樹中插入一個元素

void InsertBSTree(struct BSTNode *pBST,int InsertVal) //插入元素 {struct BSTNode *pRoot = pBST;//記錄根節(jié)點地址struct BSTNode *pNew = (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pNew)exit(-1);pNew ->data = InsertVal;pNew ->pLchild = pNew ->pRchild = NULL;struct BSTNode *pTmp = NULL;while(NULL != pBST ){pTmp = pBST;if(pNew ->data < pBST ->data)pBST = pBST ->pLchild;elsepBST = pBST ->pRchild;}pNew->pParent = pTmp;if(NULL == pTmp) //當樹為空時,將插入節(jié)點的地址賦給根節(jié)點*pRoot = *pNew;else if(pNew ->data <= pTmp ->data)pTmp ->pLchild = pNew;elsepTmp ->pRchild = pNew; }

6.刪除二叉樹中的元素

void DeleteBSTree(struct BSTNode *pBST,int DeleteVal) {struct BSTNode *pTem = SearchBSTree(pBST,DeleteVal);if(pTem == NULL){printf("沒有找到要刪除的元素!\n");exit(-1);}if(NULL == pTem ->pLchild && NULL == pTem ->pRchild) //刪除節(jié)點無左右孩子{if(pTem == pTem ->pParent ->pLchild) //刪除節(jié)點是其父節(jié)點的左孩子{pTem ->pParent ->pLchild = NULL;}else //刪除節(jié)點是其父節(jié)點的右孩子{pTem ->pParent ->pRchild =NULL;}free(pTem);pTem = NULL;}else if(NULL == pTem ->pLchild) //刪除節(jié)點無左孩子{if(pTem == pTem ->pParent ->pLchild) //刪除節(jié)點為其父節(jié)點的左孩子{pTem ->pParent ->pLchild = pTem ->pRchild;pTem ->pRchild ->pParent =pTem ->pParent;}else //刪除節(jié)點為其父節(jié)點的右孩子{pTem ->pParent ->pRchild = pTem ->pRchild;pTem ->pRchild ->pParent =pTem ->pParent;}free(pTem);pTem = NULL;}else if(NULL == pTem ->pRchild) //刪除節(jié)點無右孩子{if(pTem == pTem ->pParent->pLchild) //刪除節(jié)點為其父節(jié)點的左孩子{pTem ->pParent ->pLchild = pTem ->pLchild;pTem ->pLchild ->pParent = pTem ->pParent;}else //刪除節(jié)點為其父節(jié)點的右孩子{pTem ->pParent ->pRchild = pTem ->pLchild;pTem ->pLchild ->pParent = pTem ->pParent;}free(pTem);pTem = NULL;}else //刪除節(jié)點有左右孩子,用刪除節(jié)點左字樹中的最大值或者右子樹中最小值來代替刪除節(jié)點//本例中用右子樹中最小值來代替{struct BSTNode *pTial = pTem ->pRchild;while(NULL != pTial ->pLchild) //查找右子樹中的最小值{pTial = pTial ->pLchild;}if(pTem == pTial ->pParent) //右子樹中的最小值的父節(jié)點是刪除節(jié)點{if(pTem == pTem ->pParent ->pLchild) //刪除節(jié)點為其父節(jié)點的左孩子{pTem ->pParent ->pLchild = pTial;pTial ->pLchild = pTem ->pLchild;pTem ->pLchild->pParent = pTial;}else{pTem ->pParent ->pRchild = pTial;pTial ->pLchild = pTem ->pLchild;pTem ->pLchild->pParent = pTial;}free(pTem);pTem = NULL;}else{pTial ->pRchild ->pParent = pTial ->pParent;pTial ->pParent ->pLchild = pTial ->pRchild;pTial ->pParent ->pParent = pTial;pTial ->pRchild = pTial ->pParent;pTial ->pLchild = pTem ->pLchild;pTem ->pLchild ->pParent = pTial;if(pTem == pTem ->pParent ->pLchild){pTem ->pParent ->pLchild = pTial;}elsepTem ->pParent ->pRchild = pTial;free(pTem);pTem = NULL;}} }

7.創(chuàng)建一顆二叉搜索樹

struct BSTNode *CreateBSTree(void) {struct BSTNode * pA = (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pA)exit(-1);struct BSTNode * pB= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pB)exit(-1);struct BSTNode * pC= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pC)exit(-1);struct BSTNode * pD= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pD)exit(-1);struct BSTNode * pE= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pE)exit(-1);struct BSTNode * pF= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pF)exit(-1);struct BSTNode * pG= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pG)exit(-1);struct BSTNode * pH= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pH)exit(-1);struct BSTNode * pI= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pI)exit(-1);struct BSTNode * pJ= (struct BSTNode *)malloc(sizeof(struct BSTNode));if(NULL == pJ)exit(-1);pA ->data = 4;pB ->data = 2;pC ->data = 7;pD ->data = 3;pE ->data = 6;pF ->data = 13;pG ->data = 5;pH ->data = 10;pI ->data = 14;pJ ->data = 11;pA ->pParent = NULL;pA ->pLchild = pB;pA ->pRchild = pC;pB ->pParent = pA;pB ->pLchild = NULL;pB ->pRchild = pD;pD ->pParent = pB;pD ->pLchild = pD ->pRchild = NULL;pC ->pParent = pA;pC ->pLchild = pE;pC ->pRchild = pF;pE ->pParent = pC;pE ->pLchild = pG;pE ->pRchild = NULL;pF ->pParent = pC;pF ->pRchild = pI;pF ->pLchild =pH;pG ->pParent = pE;pG ->pLchild = pG ->pRchild = NULL;pH ->pParent = pF;pH ->pLchild = NULL;pH ->pRchild = pJ;pI ->pParent = pF;pI ->pLchild = pI ->pRchild = NULL;pJ ->pParent = pH;pJ ->pLchild = pJ ->pRchild =NULL;return pA; }

8.主函數(shù)

int main() {int MinData,MaxData;struct BSTNode *pRoot;pRoot=CreateBSTree();//printf("先序遍歷:\n");//PreTraverseBSTree(pRoot);printf("\n中序遍歷:\n");InTraverseBSTree(pRoot);//printf("\n后續(xù)遍歷:\n");//PostTraverseBSTree(pRoot);printf("\n查找的元素為: key = 5");struct BSTNode *pKeyNode = SearchBSTree(pRoot,5);if(NULL == pKeyNode)printf("查找失敗!\n");elseprintf("\n查找成功,結(jié)點地址為:%p!",pKeyNode);struct BSTNode *pMinData = SearchMinBSTree(pRoot,&MinData);printf("\n最小值為:%d,其結(jié)點地址為:%p",MinData,pMinData);struct BSTNode *pMaxDate = SearchMaxBSTree(pRoot,&MaxData);printf("\n最大值為:%d,其結(jié)點地址為:%p",MaxData,pMaxDate);printf("\n插入的元素為: data = 10");InsertBSTree(pRoot,1); //插入元素printf("\n中序遍歷:\n");InTraverseBSTree(pRoot);DeleteBSTree(pRoot,4);printf("\n中序遍歷:\n");InTraverseBSTree(pRoot);return 0; }

9.運行結(jié)果
中序遍歷:
數(shù)據(jù)為:2,父節(jié)點地址為:00e11700
數(shù)據(jù)為:3,父節(jié)點地址為:00e11718
數(shù)據(jù)為:4,父節(jié)點地址為:00000000
數(shù)據(jù)為:7,父節(jié)點地址為:00e11700
數(shù)據(jù)為:6,父節(jié)點地址為:00e11730
數(shù)據(jù)為:5,父節(jié)點地址為:00e11760
數(shù)據(jù)為:13,父節(jié)點地址為:00e11730
數(shù)據(jù)為:10,父節(jié)點地址為:00e11778
數(shù)據(jù)為:11,父節(jié)點地址為:00e117a8
數(shù)據(jù)為:14,父節(jié)點地址為:00e11778

查找的元素為: key = 5
查找成功,結(jié)點地址為:00e11790!
最小值為:2,其結(jié)點地址為:00e11718
最大值為:14,其結(jié)點地址為:00e117c0
插入的元素為: data = 10
中序遍歷:
數(shù)據(jù)為:2,父節(jié)點地址為:00e11700
數(shù)據(jù)為:1,父節(jié)點地址為:00e11718
數(shù)據(jù)為:3,父節(jié)點地址為:00e11718
數(shù)據(jù)為:4,父節(jié)點地址為:00000000
數(shù)據(jù)為:7,父節(jié)點地址為:00e11700
數(shù)據(jù)為:6,父節(jié)點地址為:00e11730
數(shù)據(jù)為:5,父節(jié)點地址為:00e11760
數(shù)據(jù)為:13,父節(jié)點地址為:00e11730
數(shù)據(jù)為:10,父節(jié)點地址為:00e11778
數(shù)據(jù)為:11,父節(jié)點地址為:00e117a8
數(shù)據(jù)為:14,父節(jié)點地址為:00e11778

中序遍歷:
數(shù)據(jù)為:2,父節(jié)點地址為:00e11700
數(shù)據(jù)為:1,父節(jié)點地址為:00e11718
數(shù)據(jù)為:3,父節(jié)點地址為:00e11718
數(shù)據(jù)為:4,父節(jié)點地址為:00000000
數(shù)據(jù)為:10,父節(jié)點地址為:00e11778
數(shù)據(jù)為:6,父節(jié)點地址為:00e117a8
數(shù)據(jù)為:5,父節(jié)點地址為:00e11760
數(shù)據(jù)為:13,父節(jié)點地址為:00e117a8
數(shù)據(jù)為:11,父節(jié)點地址為:00e11778
數(shù)據(jù)為:14,父節(jié)點地址為:00e11778

總結(jié)

以上是生活随笔為你收集整理的利用C语言实现二叉搜索树的遍历、查找、插入、删除的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。