当前位置:   article > 正文

二叉排序树C语言实现(超级详细代码)_二叉排序树c语言代码

二叉排序树c语言代码

 今天来给大家讲解一下二叉排序树C语言代码实现

 

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAR09BVF9ncmVhdA==,size_16,color_FFFFFF,t_70,g_se,x_16

 

  1. typedef int ElemType; // 自定义数据元素为整数。
  2. // 二叉树的数据结构。
  3. typedef struct BSTNode
  4. {
  5. ElemType data; // 存放结点的数据元素。
  6. struct BSTNode* lchild; // 指向左子结点地址的指针。
  7. struct BSTNode* rchild; // 指向右子结点地址的指针。
  8. }BSTNode, * BSTree;
  9. ///
  10. // 在树TT中插入关键字为ee的新结点(递归实现),返回值:0-树中已存在关键字为ee的结点;1-成功。
  11. int Insert(BSTree* TT, ElemType* ee);
  12. // 在树TT中插入关键字为ee的新结点(非递归实现),返回值:0-树中已存在关键字为ee的结点;1-成功。
  13. int Insert1(BSTree* TT, ElemType* ee);
  14. // 用数组arr中的序列构建二叉排序树TT。
  15. // 以下两种写法都可以。
  16. //void CreateBST(BSTree *TT,int arr[],int len);
  17. void CreateBST(BSTree* TT, int* arr, int len);
  18. // 在树TT中查找值为ee的结点(递归实现),成功返回结点的地址,失败返回NULL
  19. BSTNode* Find(BSTree TT, ElemType* ee);
  20. // 在树TT中查找值为ee的结点(非递归实现),成功返回结点的地址,失败返回NULL
  21. BSTNode* Find1(BSTree TT, ElemType* ee);
  22. // 在树TT中删除值为ee的结点,成功返回0,结点不存在返回1
  23. int Delete(BSTree* TT, ElemType* ee);
  24. // 求二叉树的高度。
  25. int TreeDepth(BSTree TT);
  26. // 访问结点元素。
  27. void visit(BSTNode* pp);
  28. // 采用递归的方法对二叉树的先序遍历。
  29. void PreOrder(BSTree TT);
  30. // 采用递归的方法对二叉树的中序遍历。
  31. void InOrder(BSTree TT);
  32. // 采用递归的方法对二叉树的后序遍历。
  33. void PostOrder(BSTree TT);
  34. int main()
  35. {
  36. BSTree TT = 0; // 声明树指针变量。
  37. ElemType arr[] = { 50,66,60,26,21,30,70,68 };
  38. /*
  39. // 用数组arr中的序列构建二叉排序树TT。
  40. // 构建的二叉排序树将如下:
  41. 50
  42. / \
  43. 26 66
  44. / \ / \
  45. 21 30 60 70
  46. /
  47. 68
  48. */
  49. CreateBST(&TT, arr, sizeof(arr) / sizeof(ElemType));
  50. ElemType ee;
  51. // 在树TT中查找值为ee的结点,成功返回结点的地址,失败返回NULL
  52. ee = 30;
  53. BSTNode* ss = Find(TT, &ee);
  54. if (ss != NULL) printf("查找成功,结点的地址是%p,值是%d。\n", ss, ss->data);
  55. else printf("查找失败。\n");
  56. // 二叉树的中序遍历。
  57. printf("中序遍历结果1:"); InOrder(TT); printf("\n");
  58. // 在树TT中删除值为ee的结点,成功返回0,结点不存在返回1
  59. ee = 50;
  60. printf("从树中删除值为ee的结点,Delete()的返回值是%d。\n", Delete(&TT, &ee));
  61. // 二叉树的中序遍历。
  62. printf("中序遍历结果2:"); InOrder(TT); printf("\n");
  63. return 0;
  64. }
  65. // 二叉树的先序遍历。
  66. void PreOrder(BSTree TT)
  67. {
  68. if (TT == NULL) return;
  69. visit(TT); // 访问子树TT的根结点。
  70. PreOrder(TT->lchild); // 遍历左子树。
  71. PreOrder(TT->rchild); // 遍历右子树。
  72. }
  73. // 二叉树的中序遍历。
  74. void InOrder(BSTree TT)
  75. {
  76. if (TT == NULL) return;
  77. InOrder(TT->lchild); // 遍历左子树。
  78. visit(TT); // 访问子树TT的根结点。
  79. InOrder(TT->rchild); // 遍历右子树。
  80. }
  81. // 二叉树的后序遍历。
  82. void PostOrder(BSTree TT)
  83. {
  84. if (TT == NULL) return;
  85. PostOrder(TT->lchild); // 遍历左子树。
  86. PostOrder(TT->rchild); // 遍历右子树。
  87. visit(TT); // 访问子树TT的根结点。
  88. }
  89. // 求二叉树的高度。
  90. int TreeDepth(BSTree TT)
  91. {
  92. if (TT == NULL) return 0;
  93. int ll = TreeDepth(TT->lchild); // 求左子树的高度。
  94. int rr = TreeDepth(TT->rchild); // 求右子树的高度。
  95. return ll > rr ? ll + 1 : rr + 1; // 取左、右子树的较大者再加上根结点的高度。
  96. }
  97. // 访问结点元素。
  98. void visit(BSTNode* pp)
  99. {
  100. printf("%d ", pp->data); // 访问结点元素就是把值输出来,意思一下就行了。
  101. }
  102. // 在树TT中插入关键字为ee的新结点(递归实现),返回值:0-树中已存在关键字为ee的结点;1-成功。
  103. int Insert(BSTree* TT, ElemType* ee)
  104. {
  105. // 如果当前子树为空,创建子树的根结点。
  106. if ((*TT) == NULL)
  107. {
  108. (*TT) = (BSTree)malloc(sizeof(BSTNode));
  109. memcpy(&(*TT)->data, ee, sizeof(ElemType)); // 考虑数据元素ee为结构体的情况,采用memcpy而不是直接赋值。
  110. (*TT)->lchild = (*TT)->rchild = NULL; // 当前子树的左右孩子指针置空。
  111. return 1; // 返回成功。
  112. }
  113. if (*ee == (*TT)->data) return 0; // 如果ee已存在,返回失败。
  114. if (*ee < (*TT)->data) Insert(&(*TT)->lchild, ee); // 递归向左插入。
  115. else Insert(&(*TT)->rchild, ee); // 递归向右插入。
  116. }
  117. // 在树TT中插入关键字为ee的新结点(非递归实现),返回值:0-树中已存在关键字为ee的结点;1-成功。
  118. int Insert1(BSTree* TT, ElemType* ee)
  119. {
  120. // 如果树为空,创建树的根结点。
  121. if ((*TT) == NULL)
  122. {
  123. (*TT) = (BSTree)malloc(sizeof(BSTNode));
  124. memcpy(&(*TT)->data, ee, sizeof(ElemType)); // 考虑数据元素ee为结构体的情况,采用memcpy而不是直接赋值。
  125. (*TT)->lchild = (*TT)->rchild = NULL; // 树的左右孩子指针置空。
  126. return 1; // 返回成功。
  127. }
  128. BSTNode* pss = NULL; // 记录双亲结点的地址。
  129. BSTNode* ss = (*TT); // 用于查找的临时指针。
  130. int rl = 0; // 记录ss是双亲结点的左子树还是右子树,0-左子树;1-右子树。
  131. while (ss != NULL)
  132. {
  133. if (*ee == ss->data) return 0; // 如果ee已存在,返回失败。
  134. pss = ss; // 记录双亲结点的地址。
  135. if (*ee < ss->data) { ss = ss->lchild; rl = 0; } // 继续向左走。
  136. else { ss = ss->rchild; rl = 1; } // 继续向右走。
  137. }
  138. // 分配新结点。
  139. ss = (BSTree)malloc(sizeof(BSTNode));
  140. memcpy(&ss->data, ee, sizeof(ElemType)); // 考虑数据元素ee为结构体的情况,采用memcpy而不是直接赋值。
  141. ss->lchild = ss->rchild = NULL; // 当前子树的左右孩子指针置空。
  142. // 让双亲结点的左或右指针指向新分配的结点。
  143. if (rl == 0) pss->lchild = ss;
  144. else pss->rchild = ss;
  145. return 1; // 返回成功。
  146. }
  147. // 用数组arr中的序列构建二叉排序树TT。
  148. // 以下两种写法都可以。
  149. //void CreateBST(BSTree *TT,int arr[],int len)
  150. void CreateBST(BSTree* TT, int* arr, int len)
  151. {
  152. (*TT) = NULL;
  153. int ii = 0;
  154. for (ii = 0; ii < len; ii++)
  155. {
  156. Insert(TT, &arr[ii]); // 把数组中的元素逐个插入树中。
  157. // Insert1(TT,&arr[ii]); // 把数组中的元素逐个插入树中。
  158. }
  159. }
  160. // 在树TT中查找值为ee的结点(递归实现),成功返回结点的地址,失败返回NULL
  161. BSTNode* Find(BSTree TT, ElemType* ee)
  162. {
  163. if (TT == NULL) return NULL; // 查找失败。
  164. if (*ee == TT->data) return TT; // 查找成功。
  165. if (*ee < TT->data) return Find(TT->lchild, ee); // 递归向左查找。
  166. else return Find(TT->rchild, ee); // 递归向右查找。
  167. }
  168. // 在树TT中查找值为ee的结点(非递归实现),成功返回结点的地址,失败返回NULL
  169. BSTNode* Find1(BSTree TT, ElemType* ee)
  170. {
  171. BSTNode* ss = TT; // 用于查找的临时指针,也可以直接用TT。
  172. while (ss != NULL)
  173. {
  174. if (*ee == ss->data) return ss; // 成功找到。
  175. if (*ee < ss->data) ss = ss->lchild; // 继续向左走。
  176. else ss = ss->rchild; // 继续向右走。
  177. }
  178. return NULL;
  179. /*
  180. // 以下代码更精简,可以取代以上的代码。
  181. while ( (TT!=NULL) && (*ee!=TT->data) )
  182. {
  183. if (*ee<TT->data) TT=TT->lchild; // 继续向左走。
  184. else TT=TT->rchild; // 继续向右走。
  185. }
  186. return TT;
  187. */
  188. }
  189. // 在树TT中删除值为ee的结点,成功返回0,结点不存在返回1
  190. int Delete(BSTree* TT, ElemType* ee)
  191. {
  192. if ((*TT) == NULL) return 1; // 树为空,返回1
  193. // 1)如果树只有根结点,并且待删除的结点就是根结点。
  194. if (((*TT)->data == *ee) && ((*TT)->lchild == NULL) && ((*TT)->rchild == NULL))
  195. {
  196. free(*TT); (*TT) = 0; return 0;
  197. }
  198. BSTNode* pss = NULL; // 记录双亲结点的地址。
  199. BSTNode* ss = (*TT); // 用于查找的临时指针。
  200. int rl = 0; // 记录ss是双亲结点的左子树还是右子树,0-左子树;1-右子树。
  201. // 查找待删除的结点。
  202. while (ss != NULL)
  203. {
  204. if (*ee == ss->data) break; // 成功找到。
  205. pss = ss; // 记录双亲结点的地址。
  206. if (*ee < ss->data) { ss = ss->lchild; rl = 0; } // 继续向左走。
  207. else { ss = ss->rchild; rl = 1; } // 继续向右走。
  208. }
  209. // 结点不存在,返回1
  210. if (ss == NULL) return 1;
  211. // 2)如果待删除的结点ss是叶结点,直接删除,不会破坏二叉排序树的性质。
  212. if ((ss->lchild == NULL) && (ss->rchild == NULL))
  213. {
  214. free(ss); // 释放结点。
  215. // 修改双亲结点pss的左或右指针指向NULL
  216. if (rl == 0) pss->lchild = NULL;
  217. else pss->rchild = NULL;
  218. return 0; // 返回成功。
  219. }
  220. // 3)如果待删除的结点ss只有左子树或右子树,则让子树代替自己。
  221. if ((ss->lchild == NULL) || (ss->rchild == NULL))
  222. {
  223. if (ss->lchild != NULL) // 有左子树。
  224. {
  225. // 修改双亲结点pss的左或右指针指向ss的左子树。
  226. if (rl == 0) pss->lchild = ss->lchild;
  227. else pss->rchild = ss->lchild;
  228. }
  229. else // 有右子树。
  230. {
  231. // 修改双亲结点pss的左或右指针指向ss的右子树。
  232. if (rl == 0) pss->lchild = ss->rchild;
  233. else pss->rchild = ss->rchild;
  234. }
  235. return 0; // 返回成功。
  236. }
  237. // 4)如果待删除的结点ss有左子树和右子树,让左子树最右侧的结点代替自己,然后再删除左子树最右侧的结点。
  238. // 也可以让右子树最左侧的结点代替自己,然后删除右子树最左侧的结点。
  239. BSTNode* pss1 = ss; // 记录双亲结点的地址。
  240. BSTNode* ss1 = ss->lchild; // 用于查找的临时指针。
  241. int rl1 = 0; // 记录ss1是双亲结点的左子树还是右子树,0-左子树;1-右子树。
  242. // 左子树向右走到尽头。
  243. while (ss1->rchild != NULL)
  244. {
  245. rl1 = 1; pss1 = ss1; ss1 = ss1->rchild;
  246. }
  247. // 把左子树最右侧的结点值复制到结点ss中。
  248. // 左子树最右侧的结点ss1必定无右子树。
  249. // 修改双亲结点pss1的左或右指针指向ss1的左子树,ss1的左子树可以为空。
  250. if (rl1 == 0) pss1->lchild = ss1->lchild;
  251. else pss1->rchild = ss1->lchild;
  252. free(ss1); // 释放ss1
  253. return 0;
  254. }
  255. //删除写法二:
  256. //直接返回删除后的树
  257. BSTree Delete2(BSTree TT, ElemType ee)
  258. {
  259. BSTree f, p;
  260. //f指针记录待删除结点的双亲结点
  261. //p指针用来记录待删除结点
  262. f = NULL;
  263. p = TT;
  264. while (p)
  265. {
  266. if (p->data = ee) break;
  267. f = p;
  268. if (p->data > ee) p = p->lchild;
  269. else p = p->rchild;
  270. }
  271. //第一种情况p为NULL,即是没有待删除结点
  272. if (p == NULL) return TT;
  273. //分为两种情况,待删除结点有左子树和无左子树
  274. if (p->lchild == NULL) //无左子树
  275. {
  276. //对双亲结点进行三种讨论
  277. //第一种如果双亲结点是空
  278. if (f == NULL) TT = p->rchild;
  279. //第二种p是f的左孩子
  280. else if (f->lchild == p) f->lchild = p->rchild;
  281. //第三种p是f的右孩子
  282. else f->rchild = p->rchild;
  283. free(p);
  284. }
  285. //找到以p为根节点左子树的最右边
  286. else
  287. {
  288. //m是n的双亲结点
  289. //m为p结点,n为p结点的左孩子
  290. BSTree m = p, n = p->lchild;
  291. //找到以p为根节点左子树的最右边
  292. while (n->rchild)
  293. {
  294. m = n;
  295. n = n->rchild;
  296. }
  297. //为两种情况,以n为根节点的树有无右子树
  298. if (p == m) m->lchild = n->lchild;
  299. else m->rchild = n->lchild;
  300. p->data = n->data;
  301. free(n);
  302. }
  303. return TT;
  304. }

 

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号