【数据结构】二叉树的简单操作及简单应用

前端之家收集整理的这篇文章主要介绍了【数据结构】二叉树的简单操作及简单应用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

简介:

二叉树的应用十分广泛。根据二叉树的前序序列和中序序列,可以构造出二叉树。构造方法可以采用递归和非递归。二叉树的遍历通常有四种方法,分别是前序遍历,中序遍历,后序遍历,层序遍历。其中,前序,中序,后序又有递归和非递归两种写法。求最近公共祖先的方法同样有很多。这里选择了一种时间、空间复杂度较低的方法

本文主要分为以下几个部分:

  1. 递归与非递归建树

  2. 不同方式的遍历

  3. 寻找最近公共父节点

正文:

  1. 建树

    1. 递归

每次搜到中序序列中当前节点的位置,以此位置为界,将中序序列中的区间一分为二,然后分别传给左、右子树进行递归。

    1. 非递归

栈中存储当前节点的子树区间(LR)以及他们的父节点(即当前节点)。

每次循环,将栈顶元素出栈,先找到当前元素在中序序列中的位置,然后根据对应的区间,将左右子树的区间入栈。

直到栈空为止。

注意:

应该先让右子树入栈,再让左子树入栈,保证顺序的正确。



  1. 遍历

    1. 递归

递归遍历比较简单,在每一层分别递归访问左子树右子树,然后根据前序,中序,后序的不同,调整输出语句的位置即可。



    1. 非递归

非递归主要是用栈实现,根据遍历顺序的不同,实现方法有所不同。

      1. 前序

每次访问栈顶元素,先把栈顶元素输出并弹出,然后将左右子树分别入栈,直到栈空为止。

注意先让右子树进栈,再让左子树进栈,保证输出顺序的正确。



      1. 中序

每次访问栈顶元素,先判断是否满足输出条件:是否是叶子节点、是否是已经访问过的父节点。满足则输出、弹出。

不满足则弹出栈顶(父节点),右子树入栈,原栈顶(即父节点)入栈,左子树入栈。

直到栈空为止。


      1. 后序

如果在前序遍历中,访问完父节点后,先访问右子树,在访问左子树,得到的序列正是后续访问的逆序列。

所以用一个数组储存按上述方法遍历得到的序列,最后逆向输出即可。


    1. 层序

利用队列,访问到队头元素,把它的左右子树放到对位,直到队列为空。



  1. 寻找最近公共父节点

建一个长度大于树的高度的数组,用来存储由根到目标节点的各个节点的访问情况。

然后从任一个目标节点开始向上访问,直到根节点,一路上所有的节点都标记位“已访问”。这样,已经标记过的便是此节点的父节点之一。

最后从另一个目标节点开始向上访问,一直到找到已经访问过的节点,此节点既是此节点的父节点,又是第一个节点的父节点,因此是两个节点的公共父节点。又因为第一个出现,所以是两个节点的最近公共祖先。

空间复杂度 :小于树的高度。

时间复杂度:小于2*树的高度。

CODE:

  1. #include<iostream>
  2. #define N n+1
  3. using namespace std;
  4. typedef struct Tree
  5. {
  6. int data;
  7. int father,lson,rson;
  8. };
  9. Tree *T;
  10. int n;
  11. int *preord; //存放前序表达序列
  12. int *midord; //存放中序表达序列
  13. int now; //递归所用计数器
  14.  
  15. void find(int f1,int f2); //【042-073】 寻找最近公共祖先(实现函数
  16. void lca(); //【074-085】 寻找最近公共祖先(主函数
  17.  
  18. void oudlr1(int n); //【086-092】 前序递归
  19. void oudlr2(); //【093-115】 前序非递归
  20. void ouldr1(int n); //【116-122】 中序递归
  21. void ouldr2(); //【123-161】 中序非递归
  22. void oulrd1(int n); //【162-168】 后序递归
  23. void oulrd2(); //【169-194】 后序非递归
  24. void floor(); //【195-207】 层序
  25. void putit(int head); //【208-251】 输出函数
  26.  
  27. int make1(int l,int r); //【252-289】 递归建树
  28. void make2(); //【290-351】 非递归建树
  29. void build(); //【352-366】 建树总菜单
  30.  
  31. void init(int n,int ord[]); //【367-371】 输入序列
  32. void start(); //【372-388】 开始函数
  33.  
  34. int main()
  35. {
  36. start();
  37. build();
  38. putit(1);
  39. lca();
  40. return 0;
  41. }
  42. void find(int f1,int f2)
  43. {
  44. int bo[N];
  45. int ff1,ff2;
  46. T[1].father=1;
  47. for (int i=0;i<=n;i++)
  48. {
  49. if (T[i].data==f1)
  50. {
  51. ff1=i;
  52. }
  53. if (T[i].data==f2)
  54. {
  55. ff2=i;
  56. }
  57. }
  58. for (int i=0;i<=n;i++)
  59. {
  60. bo[i]=0;
  61. }
  62. while (ff1!=1)
  63. {
  64. bo[ff1]=1;
  65. ff1=T[ff1].father;
  66. }
  67. while (bo[T[ff2].father]==0 && ff2!=1)
  68. {
  69. ff2=T[ff2].father;
  70. }
  71. cout<<"lca:"<<T[T[ff2].father].data<<endl;
  72. }
  73. void lca()
  74. {
  75. int f1,f2;
  76. cout<<endl<<endl<<"输入要查找的两个节点,0 0 结束"<<endl;
  77. cin>>f1>>f2;
  78. while (!(f1==f2&&f1==0))
  79. {
  80. find(f1,f2);
  81. cin>>f1>>f2;
  82. }
  83. return;
  84. }
  85. void oudlr1(int n)
  86. {
  87. cout<<T[n].data<<" ";
  88. if (T[n].lson!=-1) oudlr1(T[n].lson);
  89. if (T[n].rson!=-1) oudlr1(T[n].rson);
  90. return;
  91. }
  92. void oudlr2()
  93. {
  94. int sta[N];
  95. int noww=1;
  96. sta[noww]=1;
  97. while (noww>0)
  98. {
  99. int stn=sta[noww];
  100. noww--;
  101. cout<<T[stn].data<<" ";
  102. if (T[stn].rson!=-1)
  103. {
  104. noww++;
  105. sta[noww]=T[stn].rson;
  106. }
  107. if (T[stn].lson!=-1)
  108. {
  109. noww++;
  110. sta[noww]=T[stn].lson;
  111. }
  112. }
  113. return;
  114. }
  115. void ouldr1(int n)
  116. {
  117. if (T[n].lson!=-1) ouldr1(T[n].lson);
  118. cout<<T[n].data<<" ";
  119. if (T[n].rson!=-1) ouldr1(T[n].rson);
  120. return;
  121. }
  122. void ouldr2()
  123. {
  124. int boo[N];
  125. int sta[N];
  126. int now=1;
  127. sta[1]=1;
  128. for (int i=0;i<N;i++) boo[i]=0;
  129. while (now>0)
  130. {
  131. if (boo[sta[now]]==1)
  132. {
  133. cout<<T[sta[now]].data<<" ";
  134. now--;
  135. continue;
  136. }
  137. boo[sta[now]]=1;
  138. int nn=sta[now];
  139. if (T[nn].lson==-1 && T[nn].rson==-1)
  140. {
  141. cout<<T[nn].data<<" ";
  142. now--;
  143. continue;
  144. }
  145. if (T[nn].rson!=-1)
  146. {
  147. sta[now]=T[nn].rson;
  148. now++;
  149. sta[now]=nn;
  150. }
  151. nn=sta[now];
  152. if (T[nn].lson!=-1)
  153. {
  154. now++;
  155. sta[now]=T[nn].lson;
  156. }
  157. }
  158. return;
  159. }
  160. void oulrd1(int n)
  161. {
  162. if (T[n].lson!=-1) oulrd1(T[n].lson);
  163. if (T[n].rson!=-1) oulrd1(T[n].rson);
  164. cout<<T[n].data<<" ";
  165. return;
  166. }
  167. void oulrd2()
  168. {
  169. int sta[N];
  170. int sta1[N];
  171. int noww=1,s=1;
  172. sta[noww]=1;
  173. while (noww>0)
  174. {
  175. int stn=sta[noww];
  176. noww--;
  177. sta1[s++]=T[stn].data;
  178. if (T[stn].lson!=-1)
  179. {
  180. noww++;
  181. sta[noww]=T[stn].lson;
  182. }
  183. if (T[stn].rson!=-1)
  184. {
  185. noww++;
  186. sta[noww]=T[stn].rson;
  187. }
  188. }
  189. for (int i=0;i<n;i++)
  190. cout<<sta1[n-i]<<" ";
  191. return;
  192. }
  193. void floor()
  194. {
  195. int que[N];
  196. int l=1,r=2;
  197. que[1]=1;
  198. while ((l<=r)&& (l<N))
  199. {
  200. if(T[que[l]].lson!=-1) que[r++]=T[que[l]].lson;
  201. if(T[que[l]].rson!=-1) que[r++]=T[que[l]].rson;
  202. cout<<T[que[l]].data<<" ";
  203. l++;
  204. }
  205. }
  206. void putit(int head)
  207. {
  208. cout<<endl<<"选择遍历方式:1、前序 2、中序 3、后序 4、层序"<<endl;
  209. int choose;
  210. cin>>choose;
  211. if (choose==1)
  212. {
  213. cout<<endl<<"前序遍历:"<<endl;
  214. cout<<"选择递归(0)非递归(1)"<<endl;
  215. int ch;
  216. cin>>ch;
  217. if (ch==0)
  218. oudlr1(head);
  219. else
  220. oudlr2();
  221. }
  222. else if (choose==2)
  223. {
  224. cout<<endl<<"中序遍历:"<<endl;
  225. cout<<"选择递归(0)非递归(1)"<<endl;
  226. int ch;
  227. cin>>ch;
  228. if (ch==0)
  229. ouldr1(head);
  230. else
  231. ouldr2();
  232. }
  233. else if (choose==3)
  234. {
  235. cout<<endl<<"后序遍历:"<<endl;
  236. cout<<"选择递归(0)非递归(0)"<<endl;
  237. int ch;
  238. cin>>ch;
  239. if (ch==0)
  240. oulrd1(head);
  241. else
  242. oulrd2();
  243. }
  244. else if (choose==4)
  245. {
  246. cout<<endl<<"层序遍历:"<<endl;
  247. floor();
  248. }
  249. }
  250. int make1(int l,int r)
  251. {
  252. int noww=now;
  253. T[noww].data=preord[now];
  254. if (l==r)
  255. {
  256. T[noww].lson=T[noww].rson=-1;
  257. return noww;
  258. }
  259. int mid;
  260. for (int i=l;i<=r;i++)
  261. if (midord[i]==preord[now])
  262. {
  263. mid=i;
  264. break;
  265. }
  266. if (mid!=l)
  267. {
  268. now++;
  269. T[noww].lson=make1(l,mid-1);
  270. T[T[noww].lson].father=noww;
  271. }
  272. else
  273. {
  274. T[noww].lson=-1;
  275. }
  276. if (mid!=r)
  277. {
  278. now++;
  279. T[noww].rson=make1(mid+1,r);
  280. T[T[noww].rson].father=noww;
  281. }
  282. else
  283. {
  284. T[noww].rson=-1;
  285. }
  286. return noww;
  287. }
  288. void make2()
  289. {
  290. int sta[N][3];
  291. int l=1,r=n;
  292. int noww=1;
  293. int stn=1;
  294. int mid;
  295. sta[1][0]=0;sta[1][1]=1;sta[1][2]=n;
  296. while (stn>0)
  297. {
  298. int fa=sta[stn][0];
  299. l=sta[stn][1],r=sta[stn][2];
  300. T[noww].data=preord[noww];
  301. T[noww].father=fa;
  302. if (fa!=0)
  303. {
  304. if (T[fa].lson!=0)
  305. T[fa].rson=noww;
  306. else
  307. T[fa].lson=noww;
  308. }
  309. stn--;
  310. int a,b,c;
  311. for (int i=l;i<=r;i++)
  312. if (midord[i]==preord[noww])
  313. {
  314. mid=i;
  315. break;
  316. }
  317. if (mid!=l)
  318. {
  319. stn++;
  320. a=noww;
  321. b=l;
  322. c=mid-1;
  323. }
  324. else
  325. {
  326. T[noww].lson=-1;
  327. }
  328. if (mid!=r)
  329. {
  330. if (mid==l) stn++;
  331. sta[stn][0]=noww;
  332. sta[stn][1]=mid+1;
  333. sta[stn][2]=r;
  334. if (mid!=l) stn++;
  335. }
  336. else
  337. {
  338. T[noww].rson=-1;
  339. }
  340. if (mid!=l)
  341. {
  342. sta[stn][0]=a;
  343. sta[stn][1]=b;
  344. sta[stn][2]=c;
  345. }
  346. noww++;
  347. }
  348. return;
  349. }
  350. void build()
  351. {
  352. int l=1,r=n;
  353. now=1;
  354. cout<<"选择建树方式:1、递归 2、非递归"<<endl;
  355. int choose;
  356. cin>>choose;
  357. if (choose==1)
  358. {
  359. int head=make1(l,r);
  360. }
  361. else
  362. make2();
  363. return;
  364. }
  365. void init(int n,int ord[])
  366. {
  367. for (int i=1;i<=n;i++) cin>>ord[i];
  368. return;
  369. }
  370. void start()
  371. {
  372. cout<<"请输入树的节点的个数:";
  373. cin>>n;
  374. T=new Tree[N];
  375. for (int i=1;i<=n;i++)
  376. {
  377. T[i].data=T[i].father=T[i].lson=T[i].rson=0;
  378. }
  379. cout<<"请输入树的前序遍历:";
  380. preord=new int[N];
  381. init(n,preord);
  382. cout<<"请输入树的中序遍历:";
  383. midord=new int[N];
  384. init(n,midord);
  385. return;
  386. }

猜你在找的数据结构相关文章