歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 二叉排序樹(二叉搜索樹)

二叉排序樹(二叉搜索樹)

日期:2017/3/1 10:37:00   编辑:Linux編程

動態查找表的一種理想數據結構。

二叉排序樹的定義是:二叉排序樹T是一棵樹,它或者是空,或者具備一下三條性質:

(1)、如果T的根節點的左子樹非空,其左子樹所有結點的值均小於T的根節點的值

(2)、如果T的根節點的右子樹非空,其右子樹所有結點的值均大於T的根節點的值
(3)、T的根結點的左右子樹均為二叉排序樹

下面是代碼:

文件"tree.h"

[cpp]
  1. #include<iostream>
  2. #include<stack>
  3. #include<queue>
  4. using namespace std;
  5. #define MAX_NODE_NUM 20 //樹結點最大值
  6. class Bin_Sort_Tree;
  7. //樹結點
  8. class BSTnode
  9. {
  10. int tag;//後序遍歷作為訪問標志
  11. int data;
  12. BSTnode *lchild;
  13. BSTnode *rchild;
  14. friend class Bin_Sort_Tree;
  15. };
  16. //二叉排序樹
  17. class Bin_Sort_Tree
  18. {
  19. public:
  20. int Get_data(BSTnode *p)
  21. {
  22. return p->data;
  23. }
  24. bool Search_BST(BSTnode *T,int a,BSTnode *&f,BSTnode *&p)
  25. {
  26. /*-----------------------------
  27. /在樹中查找值為a的結點,查找到
  28. /了,用p保存該結點地址,f指向
  29. /p的雙親結點
  30. /-----------------------------*/
  31. p=T;
  32. while(p)
  33. {
  34. if(p->data==a)
  35. return true;
  36. else if(p->data>a)
  37. {
  38. f=p;
  39. p=p->lchild;
  40. }
  41. else
  42. {
  43. f=p;
  44. p=p->rchild;
  45. }
  46. }
  47. return false;
  48. }
  49. //將值為a的結點插入樹中,若值已存在,就不插入
  50. void Insert_BST_1(BSTnode *&T,int a)
  51. {
  52. BSTnode *f=NULL;
  53. BSTnode *p=NULL;
  54. if(Search_BST(T,a,f,p))
  55. return; //樹中已有值相同結點,不插入
  56. else
  57. {
  58. BSTnode *s=new BSTnode;
  59. s->data=a;
  60. s->lchild=s->rchild=NULL;
  61. if(s->data>f->data)
  62. f->rchild=s;
  63. else
  64. f->lchild=s;
  65. }
  66. }
  67. void Insert_BST_2(BSTnode *&T,int a) //插入算法遞歸實現
  68. {
  69. if(!T)
  70. {
  71. cout<<"樹為空"<<endl;
  72. return;
  73. }
  74. if(T->data>a)
  75. {
  76. if(!T->lchild)
  77. {
  78. T->lchild=new BSTnode;
  79. T->lchild->data=a;
  80. T->lchild->lchild=NULL;
  81. T->lchild->rchild=NULL;
  82. return;
  83. }
  84. else
  85. Insert_BST_2(T->lchild,a);
  86. }
  87. if(T->data<a)
  88. {
  89. if(!T->rchild)
  90. {
  91. T->rchild=new BSTnode;
  92. T->rchild->data=a;
  93. T->rchild->lchild=NULL;
  94. T->rchild->rchild=NULL;
  95. return;
  96. }
  97. else
  98. Insert_BST_2(T->rchild,a);
  99. }
  100. }
  101. void Create_BSTree(BSTnode *&T) //建樹
  102. {
  103. cout<<"輸入二叉排序樹的元素,輸入-1代表結束輸入:";
  104. int num[MAX_NODE_NUM];
  105. int a,i=0;
  106. while(cin>>a && a!=-1)
  107. {
  108. num[i]=a;
  109. i++;
  110. }
  111. if(num[0]==-1)
  112. {
  113. cout<<"排序樹為空"<<endl;
  114. return;
  115. }
  116. int k=i;
  117. T=new BSTnode;
  118. T->data=num[0];
  119. T->lchild=T->rchild=NULL;
  120. for(i=1;i<k;i++)
  121. Insert_BST_1(T,num[i]);
  122. cout<<"____建樹完成____"<<endl;
  123. }
  124. void Delete_BST(BSTnode *&T,int a)//刪除結點值為a的結點
  125. {
  126. /*---------------------------------------------------------
  127. / 從樹中刪除一個節點後,要保證刪後的樹還是一棵二叉排序樹,
  128. / 刪除前,首先是在樹中查找是否有這個結點,用p指向該結點,
  129. / 用f指向p的雙親結點,這個結點在樹中的位置有下面四種情況:
  130. /
  131. / 1:如果p指向的結點是葉子結點,那麼直接將f指針的左子樹或者
  132. / 右子樹置空,然後刪除p結點即可。
  133. /
  134. / 2:如果p指向的結點是只有左子樹或右子樹,那麼只需要讓p結點
  135. / 原來在f中的位置(左子樹或右子樹)用p的子樹代替即可。
  136. /
  137. / 3:如果p所指向的結點是根節點,那麼直接將根節點置空
  138. /
  139. / 4:如果p所指向的結點左右子樹都非空,為了刪除p後原序列的順
  140. / 序不變,就需要在原序列中先找出p的直接前驅(或者直接後繼)
  141. / 結點用那個結點的值來代替p結點的值,然後再刪掉那個直接前
  142. / 驅(或者直接後繼)結點。
  143. / 在中序遍歷序列中找結點的直接前驅的方法是順著結點的左孩子
  144. / 的右鏈域開始,一直到結點右孩子為空為止。
  145. /---------------------------------------------------------*/
  146. BSTnode *f=NULL;
  147. BSTnode *p=NULL;
  148. BSTnode *q=NULL;
  149. BSTnode *s=NULL;
  150. if(Search_BST(T,a,f,p))
  151. {
  152. if(p->lchild && p->rchild)
  153. {
  154. q=p;
  155. s=p->lchild;
  156. while(s->rchild)
  157. {
  158. q=s;
  159. s=s->rchild;
  160. }
  161. p->data=s->data;
  162. //s指向要刪除結點的直接前驅,且s是一定沒有右子樹的
  163. if(q!=p)
  164. q->rchild=s->lchild;
  165. else
  166. q->lchild=s->lchild;//這種情況是,q的左子樹的右子樹為空時
  167. delete s;
  168. cout<<"結點刪除成功"<<endl;
  169. return ;
  170. }
  171. else
  172. {
  173. if(!p->lchild) //左子樹為空
  174. {
  175. q=p;
  176. p=p->rchild;
  177. }
  178. else //右子樹為空
  179. {
  180. q=p;
  181. p=p->lchild;
  182. }
  183. //下面將p所指向的子樹連接到f所指(被刪結點的雙親)的結點上
  184. if(!T) //被刪的結點為根節點
  185. T=p;
  186. else if(q==f->lchild)
  187. f->lchild=p;
  188. else
  189. f->rchild=p;
  190. delete q;
  191. cout<<"結點刪除成功"<<endl;
  192. return;
  193. }
  194. }
  195. else
  196. {
  197. cout<<"要刪除的結點不存在"<<endl;
  198. return ;
  199. }
  200. }
  201. //下面是二叉樹的四種遍歷方式,都是非遞歸方式實現
  202. void PreOrder_Traverse(BSTnode *T) //前序遍歷
  203. {
  204. stack<BSTnode *> s;
  205. BSTnode *p;
  206. p=T;
  207. while(p || !s.empty())
  208. {
  209. if(p)
  210. {
  211. cout<<p->data<<" ";
  212. s.push(p);
  213. p=p->lchild;
  214. }
  215. else
  216. {
  217. p=s.top();
  218. s.pop();
  219. p=p->rchild;
  220. }
  221. }
  222. }
  223. void InOrder_Traverse(BSTnode *T) //中序遍歷
  224. {
  225. stack<BSTnode *> s;
  226. BSTnode *p=T;
  227. while(p || !s.empty())
  228. {
  229. if(p)
  230. {
  231. s.push(p);
  232. p=p->lchild;
  233. }
  234. else
  235. {
  236. p=s.top();
  237. s.pop();
  238. cout<<p->data<<" ";
  239. p=p->rchild;
  240. }
  241. }
  242. }
  243. void PostOrder_Traverse(BSTnode *T) //後序遍歷
  244. {
  245. stack<BSTnode *> s;
  246. BSTnode *p=T;
  247. while(p || !s.empty())
  248. {
  249. if(p)
  250. {
  251. p->tag=0;
  252. s.push(p);
  253. p=p->lchild;
  254. }
  255. else
  256. {
  257. p=s.top();
  258. if(p->tag)
  259. {
  260. cout<<p->data<<" ";
  261. s.pop();
  262. p=NULL;
  263. }
  264. else
  265. {
  266. p->tag=1;
  267. p=p->rchild;
  268. }
  269. }
  270. }
  271. }
  272. void LevelOrder_Traverse(BSTnode *T) //層次遍歷
  273. {
  274. queue<BSTnode *> q;
  275. BSTnode *p=T;
  276. q.push(p);
  277. while(!q.empty())
  278. {
  279. p=q.front();
  280. q.pop();
  281. cout<<p->data<<" ";
  282. if(p->lchild)
  283. q.push(p->lchild);
  284. if(p->rchild)
  285. q.push(p->rchild);
  286. }
  287. }
  288. };
Copyright © Linux教程網 All Rights Reserved