Java实现二叉树的遍历

Java实现二叉树的遍历

2023年6月22日发(作者:)

一、数据结构分类

(一)按逻辑结构

1. 集合(无辑关系)

2. 线性结构(线性表):数组、链表、栈、队列

3. 非线性结构:树、图、多维数组

(二)按存储结构

顺序(数组)储结构、链式储结构、索引储结构、散列储结构

二、二叉树相关性质

结点的度:一个结点的子树的个数记为该结点的度.

树的度:所有节点中度数最大的结节的度数,叶子节点的度为零。

树的高度:一棵树的最大层次数记为树的高度(或深度)。

有序(无序)树:若将树中结点的各子树看成是从左到右具有次序的,即不能交换,则称该树为有序树。否则称为无序树。

二叉树第i层(i≥1)上至多有2^(i-1)个节点。

深度为k的二叉树至多有2^k-1个节点(k≥1)。

对任何一棵二叉,若叶子节点数为n0,度为2的节点数为n2,则n0=n2+1。

具有n个节点的完全二叉树的深度为 (㏒2^n)(向下取整)+1。

对一棵有n个节点的完全二叉树的节点按层次从上到下,自左至右进行编号,则对任一节点i(1≤i≤n)有:若 i=1,则节点i是二叉树的根,无双亲;若 i>1,则其双亲为 i/2(向下取整)。若2i>n,则节点i没有孩子节点,否则其左孩子为2i。若2i+1>n,则节点i没有右孩子,否则其右孩子为2i+1。

若深度为k的二叉树有2^k-1个节点,则称其为满二叉树。满二叉树是一棵完全二叉树。

对于完全二叉树中,度为1的节点个数只可能为1个或0个。 对于二叉树,如果叶子节点数为n0,度为1的节点数为n1,度为2的节点数为n2,则节点总数n = n0 + n1 + n2。

对于任意树,总节点数 = 每个节点度数和 + 1

二叉树的高度等于根与最远叶节点(具有最多祖先的节点)之间分支数目。空树的高度是-1。只有单个元素的二叉树,其高度为0。

.

三、二叉树的遍历

遍历是按某种策略访问树中的每个节点,且仅访问一次。

(一) 二叉树结构实现

Java代码

1. package e;

2. /**

3. * 创建 非完全二叉树、完全二叉树、满二叉树

4. *

5. * 由于二叉树的节点增加没有什么规则,所以这里只是简单的使用了递一

6. * 次性把整棵树创建出来,而没有设计出一个一个添加节点的方法与删除

7. *

8. * @author jzj

9. * @date 2009-12-23

10. */

class BinTree {// Bin=Binary(二进位的, 二元的)

12.

13. protected Entry root;//根

14. private int size;//树的节点数

15.

16. /**

17. * 树的节点结构

18. * @author jzj

19. * @date 2009-12-23

20. */ 21. protected static class Entry {

22. int elem;//数据域,这里我们作为编号

23. Entry left;//左子树

24. Entry right;//右子树

25.

26. public Entry(int elem) {

27. = elem;

28. }

29.

30. public String toString() {

31. return " number=" + elem;

32. }

33. }

34.

35. /**

36. * 根据给定的节点数创建一个完全二叉树或是满二叉树

37. * @param nodeCount 要创建节点总数

38. */

39. public void createFullBiTree(int nodeCount) {

40. root = recurCreateFullBiTree(1, nodeCount);

41. }

42.

43. /**

44. * 递归创建完全二叉树

45. * @param num 节点编号

46. * @param nodeCount 节点总数

47. * @return TreeNode 返回创建的节点

48. */

49. private Entry recurCreateFullBiTree(int num, int nodeCount) {

50. size++;

51. Entry rootNode = new Entry(num);//根节点

52. //如果有左子树则创建左子树

53. if (num * 2 <= nodeCount) {

54. = recurCreateFullBiTree(num * 2, nodeCount);

55. //如果还可以创建右子树,则创建

56. if (num * 2 + 1 <= nodeCount) {

57. = recurCreateFullBiTree(num * 2

+ 1, nodeCount);

58. }

59. }

60. return (Entry) rootNode;

61. } 62.

63. /**

64. * 根据给定的数组创建一棵树,这个棵树可以是完全二叉树也可是普通二叉树

65. * 数组中为0的表示不创建该位置上的节点

66. * @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

67. */

68. public void createBinTree(int[] nums) {

69. root = recurCreateBinTree(nums, 0);

70. }

71.

72. /**

73. * 递归创建二叉树

74. * @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

75. * @param index 需要使用数组中的哪个元素创建节点,如果为元素为0,则不创建

76. * @return TreeNode 返回创建的节点,最终会返回树的根节点

77. */

78. private Entry recurCreateBinTree(int[] nums, int index) {

79. //指定索引上的编号不为零上才需创建节点

80. if (nums[index] != 0) {

81. size++;

82. Entry rootNode = new Entry(nums[index]);//根节点

83. //如果有左子树则创建左子树

84. if ((index + 1) * 2 <= ) {

85. = (Entry) recurCreateBinTree(nums, (index + 1) * 2 - 1);

86. //如果还可以创建右子树,则创建

87. if ((index + 1) * 2 + 1 <= ) {

88. = (Entry) recurCreateBinTree(nums, (index + 1) * 2);

89. }

90. }

91. return (Entry) rootNode;

92. }

93. return null;

94.

95. }

96.

97. public int size() {

98. return size; 99. }

100.

101. //取树的最左边的节点

102. public int getLast() {

103. Entry e = root;

104. while ( != null) {

105. e = ;

106. }

107. return ;

108. }

109.

110. //测试

111. public static void main(String[] args) {

112.

113. //创建一个满二叉树

114. BinTree binTree = new BinTree();

115. FullBiTree(15);

116. n(());//15

117. n(t());//15

118.

119. //创建一个完全二叉树

120. binTree = new BinTree();

121. FullBiTree(14);

122. n(());//14

123. n(t());//7

124.

125. //创建一棵非完全二叉树

126. binTree = new BinTree();

127. int[] nums = new int[] { 1, 2, 3, 4, 0, 0, 5, 0, 6, 0, 0, 0, 0, 7, 8 };

128. BinTree(nums);

129. n(());//8

130. n(t());//8

131.

132. }

133. }

(二)利用二叉树本身特点进行递归遍历(属内部遍历)

由于二叉树所具有的递归性质,一棵非空的二叉树可以看作是由根节点、左子树和右子树3部分构成,因为若能依次遍历这3部分的信息,也就遍历了整个二叉树。按照左子树的遍历在右子树的遍历之前进行的约定,根据访问根节点位置的不同,可以得到二叉的前序、中序、后序3种遍历方法。

Java代码

1. package e;

2.

3. /**

4. * 二叉树的三种 内部 遍历:前序、中序、后序

5. * 但不管是哪种方式,左子树的遍历在右子树的遍历之前遍历是这有三种遍历方式都

6. * 必须遵循的约定

7. * @author jzj

8. * @date 2009-12-23

9. */

class BinTreeInOrder extends BinTree {

11.

12. /**

13. * 节点访问者,可根据需要重写visit方法

14. */

15. static abstract class Visitor {

16. void visit(Object ele) {

17. (ele + " ");

18. }

19. }

20.

21. public void preOrder(Visitor v) {

22. preOrder(v, root);

23. }

24.

25. /**

26. * 树的前序递归遍历 pre=prefix(前缀)

27. * @param node 要遍历的节点

28. */

29. private void preOrder(Visitor v, Entry node) {

30. //如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

31. if (node != null) {

32. ();//先遍历父节点

33. preOrder(v, );//再遍历左节点

34. preOrder(v, );//最后遍历右节点

35. }

36. }

37. 38. public void inOrder(Visitor v) {

39. inOrder(v, root);

40. }

41.

42. /**

43. * 树的中序递归遍历 in=infix(中缀)

44. * @param node 要遍历的节点

45. */

46. private void inOrder(Visitor v, Entry node) {

47. //如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

48. if (node != null) {

49. inOrder(v, );//先遍历左节点

50. ();//再遍历父节点

51. inOrder(v, );//最后遍历右节点

52. }

53. }

54.

55. public void postOrder(Visitor v) {

56. postOrder(v, root);

57. }

58.

59. /**

60. * 树的后序递归遍历 post=postfix(后缀)

61. * @param node 要遍历的节点

62. */

63. private void postOrder(Visitor v, Entry node) {

64. //如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

65. if (node != null) {

66. postOrder(v, );//先遍历左节点

67. postOrder(v, );//再遍历右节点

68. ();//最后遍历父节点

69. }

70. }

71.

72. //测试

73. public static void main(String[] args) {

74.

75. //创建二叉树

76. int[] nums = new int[] { 1, 2, 3, 4, 0, 0, 5, 0, 6, 0,

0, 0, 0, 7, 8 };

77. BinTreeInOrder treeOrder = new BinTreeInOrder();

78. BinTree(nums); 79. ("前序遍历 - ");

80. er(new Visitor() {

81. });

82. n();

83. ("中序遍历 - ");

84. r(new Visitor() {

85. });

86. n();

87. ("后序遍历 - ");

88. der(new Visitor() {

89. });

90. /*

91. * output:

92. * 前序遍历 - 1 2 4 6 3 5 7 8

93. * 中序遍历 - 4 6 2 1 3 7 5 8

94. * 后序遍历 - 6 4 2 7 8 5 3 1

95. */

96. }

97.}

(三)二叉树的非递归遍历(属外部遍历)

1、利用栈与队列对二叉树进行非递归遍历

Java代码

1. package e;

2.

3. import or;

4. import List;

5. import ;

6.

7. /**

8. * 二叉树的外部遍历:深度优先(先根)、广度(层次)优先遍历

9. *

10. * @author jzj

11. * @date 2009-12-23

12. */

class BinTreeOutOrder extends BinTree {

14.

15. /**

16. * 二叉树深序优先遍历(即二叉树的先根遍历)迭代器,外部可以使用该迭代器 17. * 进行非递归的遍历,这是一种在二叉树结构外部的一种遍历算法,它没有使用

18. * 二叉树本身的结构特点(左右子树递归)进行递归遍历

19. * @author jzj

20. */

21. private class DepthOrderIterator implements Iterator {

22. //栈里存放的是每个节点

23. private Stack stack = new Stack();

24.

25. public DepthOrderIterator(Entry node) {

26.

27. //根入栈,但在放入左右子节点前会马上出栈,即根先优于左右子节点访问

28. (node);

29.

30. }

31.

32. //是否还有下一个元素

33. public boolean hasNext() {

34. if (y()) {

35. return false;

36. }

37. return true;

38. }

39.

40. //取下一个元素

41. public Entry next() {

42. if (hasNext()) {

43. //取栈顶元素

44. Entry treeNode = (Entry) ();//先访问根

45.

46. if ( != null) {

47. ();//再放入右子节点

48. }

49.

50. if ( != null) {

51. ();//最后放入左子节点,但访问先于右节点

52. }

53.

54. // 返回遍历得到的节点

55. return treeNode; 56.

57. } else {

58. // 如果栈为空

59. return null;

60. }

61. }

62.

63. public void remove() {

64. throw new UnsupportedOperationException();

65. }

66.

67. }

68.

69. /**

70. * 向外界提供先根遍历迭代器

71. * @return Iterator 返回先根遍历迭代器

72. */

73. public Iterator createPreOrderItr() {

74. return new DepthOrderIterator(root);

75. }

76.

77. /**

78. * 二叉树广度优先遍历迭代器,外部可以使用该迭代器

79. * 进行非递归的遍历,这是一种在二叉树结构外部的一种遍历算法,它没有使用

80. * 二叉树本身的结构特点(左右子树递归)进行递归遍历

81. * @author jzj

82. */

83. private class LevelOrderIterator implements Iterator {

84. //使用队列结构实现层次遍历,队列里存储的为节点

85. private LinkedList queue = new LinkedList();

86.

87. public LevelOrderIterator(Entry node) {

88.

89. if (node != null) {

90. //将根入队

91. t(node);

92. }

93. }

94.

95. //是否还有下一个元素

96. public boolean hasNext() {

97. if (y()) {

98. return false; 99. }

100. return true;

101. }

102.

103. //取下一个元素

104. public Entry next() {

105. if (hasNext()) {

106. //取栈顶迭元素

107. Entry treeNode = (Entry) First();

108.

109. if ( != null) {//如果有左子树,加入有序列表中

110. t();

111. }

112. if ( != null) {//如果有右子树,加入有序列表中

113. t();

114. }

115.

116. // 返回遍历得到的节点

117. return treeNode;

118.

119. } else {

120. // 如果队列为空

121. return null;

122. }

123. }

124.

125. public void remove() {

126. throw new UnsupportedOperationException();

127. }

128.

129. }

130.

131. /**

132. * 向外界提供广度优先迭代器

133. * @return Iterator 返回遍历迭代器

134. */

135. public Iterator createLayerOrderItr() {

136. return new LevelOrderIterator(root);

137. }

138.

139. public static void main(String[] args) { 140. //创建一棵满二叉树

141. BinTreeOutOrder treeOrder = new BinTreeOutOrder();

142. FullBiTree(15);

143. Iterator preOrderItr = PreOrderItr();

144. ("深度优先(先根)遍历 - ");

145. while (t()) {

146. (((Entry) ()).elem + " ");

147. }

148. n();

149. ("广度优先(层次)遍历 - ");

150. Iterator layerOrderItr = LayerOrderItr();

151. while (t()) {

152. (((Entry) ()).elem + " ");

153. }

154. /*

155. * output:

156. * 深度优先(先根)遍历 - 1 2 4 8 9 5 10 11 3 6 12 13 7 14 15

157. * 广度优先(层次)遍历 - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

158. */

159. }

160. }

2、利用二叉树节点的父节点指针进行非递归遍历

要想采用非递归的方法遍历树,又不借助于前面的队列与栈,我们需要该树是一棵可回溯的二叉树,即从子节点要能够知道他的父节点及祖先节点,与前面的二叉树不同的是,树的节点结构体中多一个指向父的节点指针,这样外界可以以非递归的方式来遍历二叉树了 。

Java代码

1. package e;

2.

3. /**

4. *

5. * 可回溯的二叉树

6. * 二叉树的非递归遍历 7. *

8. * @author jzj

9. * @date 2009-12-23

10. */

class BackBinTree {// Bin=Binary(二进位的, 二元的)

12.

13. protected Entry root;//根

14. private int size;//树的节点数

15.

16. /**

17. * 树的节点结构

18. * @author jzj

19. * @date 2009-12-23

20. */

21. private static class Entry {

22. int elem;//数据域,这里为了测试,就作为节点编号吧

23. Entry paraent;//父节点

24. Entry left;//左节点

25. Entry right;//右节点

26.

27. //构造函数只有两个参数,左右节点是调用add方法时设置

28. public Entry(int elem, Entry parent) {

29. = elem;

30. t = parent;

31. }

32. }

33.

34. /**

35. * 查找前序遍历(根左右)直接后继节点

36. *

37. * 以非递归 根左右 的方式遍历树

38. *

39. * @param e 需要查找哪个节点的直接后继节点

40. * @return Entry 前序遍历直接后继节点

41. */

42. public Entry preOrderSuccessor(Entry e) {

43. if (e == null) {

44. return null;

45. }//如果左子树不为空,则直接后继为左子节点

46. else if ( != null) {//先看左子节点是否为空

47. return ;//如果不为空,则直接后继为左子节点

48. }//否则如果右子树不为空,则直接后继为右子节点

49. else if ( != null) {//如果左子节点为空,则看右子节点是否为空 50. return ;//如果右子节点不为空,则返回

51. }//左右子节点都为空的情况下

52. else {

53. Entry s = t;

54. Entry c = e;

55.

56. /*

57. * 一直向上,直到c是s的左子树,且s的右子树不为空。请试着找一下36与68节点的

58. * 直接后继节点,36的应该是75,而68则没有后继节点了

59. *

60. * 50

61. * /

62. * 37 75

63. * / /

64. * 25 61

65. * / /

66. * 15 30 55 68

67. * /

68. * 28 32 59

69. *

70. * 36

71. */

72. while (s != null && (c == || == null)) {

73. c = s;

74. s = t;

75. }

76. //退出循环时 s 可以为null,比如查找 68 节点的直接后继时退出循环时s=null

77. if (s == null) {

78. return null;

79. } else {

80. return ;

81. }

82. }

83. }

84.

85. /**

86. * 查找前序遍历(根左右)直接前驱节点

87. *

88. * 以非递归 右左根 的方式遍历树

89. *

90. * @param e 需要查找哪个节点的直接前驱节点 91. * @return Entry 前序遍历直接前驱节点

92. */

93. public Entry preOrderAncestor(Entry e) {

94. if (e == null) {

95. return null;

96. }//如果节点为父节点的左节点,则父节点就是直接前驱节点

97. else if (t != null && e == ) {

98. return t;

99. }//如果节点为父节点的右节点

100. else if (t != null && e == ) {

101.

102. Entry s = t;//前驱节点默认为父节点

103. if ( != null) {//如果父节点没有左子,前驱节点就为父节点

104. s = ;//如果父节点的左子节点不空,则初始为父节点左子节点

105.

106. /*

107. * 只要父节点左子节点还有子节点,则前驱节点要从其子树中找。请试着找

108. * 一下75直接前驱节点,应该是36

109. *

110. * 50

111. * /

112. * 37 75

113. * / /

114. * 25 61

115. * / /

116. * 15 30 55 68

117. * /

118. * 28 32 59

119. *

120. * 36

121. */

122. while ( != null || != null)

{

123. //在父节点的左子节点的子树中查找时,一定要先向右边拐

124. if ( != null) {

125. s = ;

126. } else {//如果右边没有,然后才能向左边拐

127. s = ; 128. }

129. }

130. }

131. return s;

132. } else {//如果是根节点,则没有直接前驱节点了

133. return null;

134. }

135. }

136.

137. /**

138. * 查找后序遍历(左右根)直接后继节点

139. *

140. * 以非递归 左右根 的方式遍历树

141. *

142. * @param e 需要查找哪个节点的直接后继节点

143. * @return Entry 后序遍历直接后继节点

144. */

145. public Entry postOrderSuccessor(Entry e) {

146. if (e == null) {

147. return null;

148. }//如果节点为父节点的右子节点,则父节点就是直接后继节点

149. else if (t != null && e == ) {

150. return t;

151. }//如果节点为父节点的左子节点

152. else if (t != null && e == ) {

153. Entry s = t;//后继节点默认为父节点

154. if ( != null) {//如果父节点没有右子,后继节点就为父节点

155. s = ;//如果父节点的右子节点不空,则初始为父节点右子节点

156. /*

157. * 只要父节点右子节点还有子节点,则后断节点要从其子树中找,

158. * 如15的后继节点为28

159. * 50

160. * /

161. * 37 75

162. * / /

163. * 25 61

164. * / /

165. * 15 30 55 68 166. * /

167. * 28 32 59

168. *

169. * 36

170. */

171.

172. while ( != null || != null)

{

173. //在父节点的右子节点的子树中查找时,一定要先向左边拐

174. if ( != null) {

175. s = ;

176. } else {//如果左边没有,然后才能向右边拐

177. s = ;

178. }

179. }

180. }

181. return s;

182. } else {

183. //如果是根节点,则没有后继节点了

184. return null;

185. }

186. }

187.

188. /**

189. * 查找后序遍历(左右根)直接前驱节点

190. *

191. * 以非递归 根右左 的方式遍历树

192. *

193. * @param e 需要查找哪个节点的直接前驱节点

194. * @return Entry 后序遍历直接前驱节点

195. */

196. public Entry postOrderAncestor(Entry e) {

197.

198. if (e == null) {

199. return null;

200. }//如果右子树不为空,则直接前驱为右子节点

201. else if ( != null) {//先看右子节点是否为空

202. return ;//如果不为空,则直接后继为右子节点

203. }//否则如果左子树不为空,则直接前驱为左子节点

204. else if ( != null) { 205. return ;

206. }//左右子节点都为空的情况下

207. else {

208. Entry s = t;

209. Entry c = e;

210.

211. /*

212. * 一直向上,直到c是s的右子树,且s的左子树不为空。请试着找一下59与15节点的

213. * 直接后继节点,59的应该是37,而15则没有后继节点了

214. *

215. * 50

216. * /

217. * 37 75

218. * / /

219. * 25 61

220. * / /

221. * 15 30 55 68

222. * /

223. * 28 32 59

224. *

225. * 36

226. */

227. while (s != null && (c == || ==

null)) {

228. c = s;

229. s = t;

230. }

231. if (s == null) {

232. return null;

233. } else {

234. return ;

235. }

236. }

237. }

238.

239. /**

240. * 查找中序遍历(左根右)直接后继节点

241. *

242. * 以非递归 左根右 的方式遍历树

243. *

244. * @param e 需要查找哪个节点的直接后继节点

245. * @return Entry 中序遍历直接后继节点 246. */

247. public Entry inOrderSuccessor(Entry e) {

248. if (e == null) {

249. return null;

250. }//如果待找的节点有右子树,则在右子树上查找

251. else if ( != null) {

252. //默认后继节点为右子节点(如果右子节点没有左子树时即为该节点)

253. Entry p = ;

254. while ( != null) {

255. //注,如果右子节点的左子树不为空,则在左子树中查找,且后面找时要一直向左拐

256. p = ;

257. }

258. return p;

259. }//如果待查节点没有右子树,则要在祖宗节点中查找后继节点

260. else {

261. //默认后继节点为父节点(如果待查节点为父节点的左子树,则后继为父节点)

262. Entry p = t;

263. Entry current = e;//当前节点,如果其父不为后继,则下次指向父节点

264. //如果待查节点为父节点的右节点时,继续向上找,一直要找到current为左子节点,则s才是后继

265. while (p != null && current == ) {

266. current = p;

267. p = t;

268. }

269. return p;

270. }

271. }

272.

273. /**

274. * 查找中序遍历(左根右)直接前驱节点

275. *

276. * 以非递归 右根左 的方式遍历树

277. *

278. * @param e 需要查找哪个节点的直接前驱节点

279. * @return Entry 中序遍历直接前驱节点

280. */

281. public Entry inOrderAncestor(Entry e) {

282. if (e == null) {

283. return null; 284. }//如果待找的节点有左子树,则在在子树上查找

285. else if ( != null) {

286. //默认直接前驱节点为左子节点(如果左子节点没有右子树时即为该节点)

287. Entry p = ;

288. while ( != null) {

289. //注,如果左子节点的右子树不为空,则在右子树中查找,且后面找时要一直向右拐

290. p = ;

291. }

292. return p;

293. }//如果待查节点没有左子树,则要在祖宗节点中查找前驱节点

294. else {

295. //默认前驱节点为父节点(如果待查节点为父节点的右子树,则前驱为父节点)

296. Entry p = t;

297. Entry current = e;//当前节点,如果其父不为前驱,则下次指向父节点

298. //如果待查节点为父节点的左节点时,继续向上找,一直要找到current为p的右子节点,则s才是前驱

299. while (p != null && current == ) {

300. current = p;

301. p = t;

302. }

303. return p;

304. }

305. }

306.

307. /**

308. * 查找指定的节点

309. * @param num

310. * @return Entry

311. */

312. public Entry getEntry(int num) {

313. return getEntry(root, num);

314. }

315.

316. /**

317. * 使用树的先序遍历递归方式查找指定的节点

318. *

319. * @param entry

320. * @param num

321. * @return 322. */

323. private Entry getEntry(Entry entry, int num) {

324.

325. //如果找到,则停止后续搜索,并把查找到的节点返回给上层调用者

326. if ( == num) {//1、先与父节点比对

327. return entry;

328. }

329.

330. Entry tmp = null;

331.

332. if ( != null) {//2、再在左子树上找

333. tmp = getEntry(, num);

334. //如果左子树上找到,返回并停止查找,否则继续在后续节点中找

335. if (tmp != null) {

336. //节点在左子树中找到,返回给上层调用者

337. return tmp;

338. }

339. }

340.

341. if ( != null) {//3、否则在右子树上找

342. tmp = getEntry(, num);

343. //如果右子树上找到,返回并停止查找,否则继续在后续节点中找

344. if (tmp != null) {

345. //节点在右子树中找到,返回给上层调用者

346. return tmp;

347. }

348. }

349.

350. //当前比较节点 entry 子树为空或不为空时没有找到,直接返回给上层调用者null

351. return null;

352. }

353.

354. /**

355. * 根据给定的数组创建一棵树,这个棵树可以是完全二叉树也可是普通二叉树

356. * 数组中为0的表示不创建该位置上的节点

357. * @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

358. */

359. public void createBinTree(int[] nums) { 360. root = recurCreateBinTree(nums, null, 0);

361. }

362.

363. /**

364. * 递归创建二叉树

365. * @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

366. * @param paraent 父节点

367. * @param index 需要使用数组中的哪个元素创建节点,如果为元素为0,则不创建

368. * @return Entry 返回创建的节点,最终会返回树的根节点

369. */

370. private Entry recurCreateBinTree(int[] nums, Entry pararent, int index) {

371. //指定索引上的编号不为零上才需创建节点

372. if (nums[index] != 0) {

373. size++;

374. Entry root = new Entry(nums[index], pararent);//根节点

375. //如果有左子树则创建左子树

376. if ((index + 1) * 2 <= ) {

377. = (Entry) recurCreateBinTree(nums, root, (index + 1) * 2 - 1);

378. //如果还可以创建右子树,则创建

379. if ((index + 1) * 2 + 1 <= ) {

380. = (Entry) recurCreateBinTree(nums, root, (index + 1) * 2);

381. }

382. }

383. return (Entry) root;

384. }

385. return null;

386.

387. }

388.

389. public int size() {

390. return size;

391. }

392.

393. //测试

394. public static void main(String[] args) {

395.

396. //创建一棵非完全二叉树 397. BackBinTree binTree = new BackBinTree();

398. /*

399. * 50

400. * /

401. * 37 75

402. * / /

403. * 25 61

404. * / /

405. * 15 30 55 68

406. * /

407. * 28 32 59

408. *

409. * 36

410. */

411. int[] nums = new int[] {

15, 30,

412.

0, 0, 0,

413. BinTree(nums);

414.

415. Entry entry = ry(416. ("417. while (entry != null) {

418. ( + " ");

419. entry = erSuccessor(entry);

420. }

421. n();

422. entry = ry(423. ("424. while (entry != null) {

425. ( + " ");

426. entry = erAncestor(entry);

427. }

428. n();

429. entry = ry(430. ("431. while (entry != null) {

432. ( + " ");

433. entry = derSuccessor(entry);

434. }

435. n();

436.

437. entry = ry(438. ("50, 37, 75, 25, 0, 61, 0,0, 0, 55, 68, 0, 0, 0,

0, 28, 32, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 36 };

50);

根左右(先序遍历)- ");

68);

右左根(先序的逆)- ");

15);

左右根(后序遍历)- ");

50);

根右左(后序的逆)- "); 439. while (entry != null) {

440. ( + " ");

441. entry = derAncestor(entry);

442. }

443. n();

444.

445. entry = ry(15);

446. ("左根右(中序遍历)- ");

447. while (entry != null) {

448. ( + " ");

449. entry = rSuccessor(entry);

450. }

451. n();

452.

453. entry = ry(75);

454. ("右根左(中序的逆)- ");

455. while (entry != null) {

456. ( + " ");

457. entry = rAncestor(entry);

458. }

459. n();

460. /*

461. * output:

462. * 根左右(先序遍历)- 50 37 25 15 30 28 32 36 75 61 55 59 68

463. * 右左根(先序的逆)- 68 59 55 61 75 36 32 28 30 15 25 37 50

464. * 左右根(后序遍历)- 15 28 36 32 30 25 37 59 55 68 61 75 50

465. * 根右左(后序的逆)- 50 75 61 68 55 59 37 25 30 32 36 28 15

466. * 左根右(中序遍历)- 15 25 28 30 32 36 37 50 55 59 61 68 75

467. * 右根左(中序的逆)- 75 68 61 59 55 50 37 36 32 30 28 25 15

468. */

469. }

470. } 

大小: 1.4 KB

大小: 12.3 KB

package e;

/**

* 创建 非完全二叉树、完全二叉树、满二叉树

*

* 由于二叉树的节点增加没有什么规则,所以这里只是简单的使用了递一 * 次性把整棵树创建出来,而没有设计出一个一个添加节点的方法与删除

*

* @author jzj

* @date 2009-12-23

*/

public class BinTree {// Bin=Binary(二进位的, 二元的)

protected Entry root;//根

private int size;//树的节点数

/**

* 树的节点结构

* @author jzj

* @date 2009-12-23

*/

protected static class Entry {

int elem;//数据域,这里我们作为编号

Entry left;//左子树

Entry right;//右子树

public Entry(int elem) {

= elem;

}

public String toString() {

return " number=" + elem;

}

}

/**

* 根据给定的节点数创建一个完全二叉树或是满二叉树

* @param nodeCount 要创建节点总数

*/

public void createFullBiTree(int nodeCount) {

root = recurCreateFullBiTree(1, nodeCount);

}

/**

* 递归创建完全二叉树

* @param num 节点编号

* @param nodeCount 节点总数

* @return TreeNode 返回创建的节点

*/

private Entry recurCreateFullBiTree(int num, int nodeCount) {

}

size++;

Entry rootNode = new Entry(num);//根节点

//如果有左子树则创建左子树

if (num * 2 <= nodeCount) {

= recurCreateFullBiTree(num * 2, nodeCount);

//如果还可以创建右子树,则创建

if (num * 2 + 1 <= nodeCount) {

= recurCreateFullBiTree(num * 2 + 1, nodeCount);

}

}

return (Entry) rootNode;

/**

* 根据给定的数组创建一棵树,这个棵树可以是完全二叉树也可是普通二叉树

* 数组中为0的表示不创建该位置上的节点

* @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

*/

public void createBinTree(int[] nums) {

root = recurCreateBinTree(nums, 0);

}

/**

* 递归创建二叉树

* @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

* @param index 需要使用数组中的哪个元素创建节点,如果为元素为0,则不创建

* @return TreeNode 返回创建的节点,最终会返回树的根节点

*/

private Entry recurCreateBinTree(int[] nums, int index) {

//指定索引上的编号不为零上才需创建节点

if (nums[index] != 0) {

size++;

Entry rootNode = new Entry(nums[index]);//根节点

//如果有左子树则创建左子树

if ((index + 1) * 2 <= ) {

= (Entry) recurCreateBinTree(nums, (index + 1) * 2 - 1);

//如果还可以创建右子树,则创建

if ((index + 1) * 2 + 1 <= ) {

= (Entry) recurCreateBinTree(nums, (index + 1) * 2);

}

}

return (Entry) rootNode;

}

return null; }

public int size() {

return size;

}

//取树的最左边的节点

public int getLast() {

Entry e = root;

while ( != null) {

e = ;

}

return ;

}

//测试

public static void main(String[] args) {

//创建一个满二叉树

BinTree binTree = new BinTree();

FullBiTree(15);

n(());//15

n(t());//15

//创建一个完全二叉树

binTree = new BinTree();

FullBiTree(14);

n(());//14

n(t());//7

//创建一棵非完全二叉树

binTree = new BinTree();

int[] nums = new int[] { 1, 2, 3, 4, 0, 0, 5, 0, 6, 0, 0, 0, 0, 7, 8 };

BinTree(nums);

n(());//8

n(t());//8

}

package e;

/**

* 二叉树的三种 内部 遍历:前序、中序、后序

* 但不管是哪种方式,左子树的遍历在右子树的遍历之前遍历是这有三种遍历方式都

* 必须遵循的约定

* @author jzj

* @date 2009-12-23

*/

public class BinTreeInOrder extends BinTree {

/**

* 节点访问者,可根据需要重写visit方法

*/

static abstract class Visitor {

void visit(Object ele) {

(ele + " ");

}

}

public void preOrder(Visitor v) {

preOrder(v, root);

}

/**

* 树的前序递归遍历 pre=prefix(前缀)

* @param node 要遍历的节点

*/

private void preOrder(Visitor v, Entry node) {

//如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

if (node != null) {

();//先遍历父节点

preOrder(v, );//再遍历左节点

preOrder(v, );//最后遍历右节点

}

}

public void inOrder(Visitor v) {

inOrder(v, root);

}

/**

* 树的中序递归遍历 in=infix(中缀)

* @param node 要遍历的节点

*/

private void inOrder(Visitor v, Entry node) {

//如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

if (node != null) {

inOrder(v, );//先遍历左节点

();//再遍历父节点

inOrder(v, );//最后遍历右节点

}

}

public void postOrder(Visitor v) {

postOrder(v, root);

}

/**

* 树的后序递归遍历 post=postfix(后缀)

* @param node 要遍历的节点

*/

private void postOrder(Visitor v, Entry node) {

//如果传进来的节点不为空,则遍历,注,叶子节点的子节点为null

if (node != null) {

postOrder(v, );//先遍历左节点

postOrder(v, );//再遍历右节点

();//最后遍历父节点

}

} //测试

public static void main(String[] args) {

//创建二叉树

int[] nums = new int[] { 1, 2, 3, 4, 0, 0, 5, 0, 6, 0, 0, 0, 0, 7, 8 };

BinTreeInOrder treeOrder = new BinTreeInOrder();

BinTree(nums);

("前序遍历 - ");

er(new Visitor() {

});

n();

("中序遍历 - ");

r(new Visitor() {

});

n();

("后序遍历 - ");

der(new Visitor() {

});

/*

* output:

* 前序遍历 - 1 2 4 6 3 5 7 8

* 中序遍历 - 4 6 2 1 3 7 5 8

* 后序遍历 - 6 4 2 7 8 5 3 1

*/

}

package e;

import or;

import List;

import ;

/**

* 二叉树的外部遍历:深度优先(先根)、广度(层次)优先遍历

*

* @author jzj

* @date 2009-12-23

*/

public class BinTreeOutOrder extends BinTree {

/**

* 二叉树深序优先遍历(即二叉树的先根遍历)迭代器,外部可以使用该迭代器

* 进行非递归的遍历,这是一种在二叉树结构外部的一种遍历算法,它没有使用

* 二叉树本身的结构特点(左右子树递归)进行递归遍历

* @author jzj

*/

private class DepthOrderIterator implements Iterator {

//栈里存放的是每个节点

private Stack stack = new Stack();

public DepthOrderIterator(Entry node) {

//根入栈,但在放入左右子节点前会马上出栈,即根先优于左右子节点访问

(node);

}

//是否还有下一个元素

public boolean hasNext() {

if (y()) {

return false;

}

return true;

}

//取下一个元素

public Entry next() {

if (hasNext()) {

//取栈顶元素

Entry treeNode = (Entry) ();//先访问根

if ( != null) {

();//再放入右子节点

}

if ( != null) {

}

}

}

();//最后放入左子节点,但访问先于右节点

// 返回遍历得到的节点

return treeNode;

} else {

// 如果栈为空

return null;

}

public void remove() {

throw new UnsupportedOperationException();

}

/**

* 向外界提供先根遍历迭代器

* @return Iterator 返回先根遍历迭代器

*/

public Iterator createPreOrderItr() {

return new DepthOrderIterator(root);

}

/**

* 二叉树广度优先遍历迭代器,外部可以使用该迭代器

* 进行非递归的遍历,这是一种在二叉树结构外部的一种遍历算法,它没有使用

* 二叉树本身的结构特点(左右子树递归)进行递归遍历

* @author jzj

*/

private class LevelOrderIterator implements Iterator {

//使用队列结构实现层次遍历,队列里存储的为节点

private LinkedList queue = new LinkedList();

public LevelOrderIterator(Entry node) {

}

if (node != null) {

//将根入队

t(node);

}

}

//是否还有下一个元素

public boolean hasNext() {

if (y()) {

return false;

}

return true;

}

//取下一个元素

public Entry next() {

if (hasNext()) {

//取栈顶迭元素

Entry treeNode = (Entry) First();

}

if ( != null) {//如果有左子树,加入有序列表中

t();

}

if ( != null) {//如果有右子树,加入有序列表中

t();

}

// 返回遍历得到的节点

return treeNode;

} else {

// 如果队列为空

return null;

}

public void remove() {

throw new UnsupportedOperationException();

}

/**

* 向外界提供广度优先迭代器

* @return Iterator 返回遍历迭代器

*/

public Iterator createLayerOrderItr() {

return new LevelOrderIterator(root);

} public static void main(String[] args) {

//创建一棵满二叉树

BinTreeOutOrder treeOrder = new BinTreeOutOrder();

FullBiTree(15);

Iterator preOrderItr = PreOrderItr();

("深度优先(先根)遍历 - ");

while (t()) {

(((Entry) ()).elem + " ");

}

n();

("广度优先(层次)遍历 - ");

Iterator layerOrderItr = LayerOrderItr();

while (t()) {

(((Entry) ()).elem + " ");

}

/*

* output:

* 深度优先(先根)遍历 - 1 2 4 8 9 5 10 11 3 6 12 13 7 14 15

* 广度优先(层次)遍历 - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

*/

}

package e;

/**

*

* 可回溯的二叉树

* 二叉树的非递归遍历 *

* @author jzj

* @date 2009-12-23

*/

public class BackBinTree {// Bin=Binary(二进位的, 二元的)

protected Entry root;//根

private int size;//树的节点数

/**

* 树的节点结构

* @author jzj

* @date 2009-12-23

*/

private static class Entry {

int elem;//数据域,这里为了测试,就作为节点编号吧

Entry paraent;//父节点

Entry left;//左节点

Entry right;//右节点

//构造函数只有两个参数,左右节点是调用add方法时设置

public Entry(int elem, Entry parent) {

= elem;

t = parent;

}

}

/**

* 查找前序遍历(根左右)直接后继节点

*

* 以非递归 根左右 的方式遍历树

*

* @param e 需要查找哪个节点的直接后继节点

* @return Entry 前序遍历直接后继节点

*/

public Entry preOrderSuccessor(Entry e) {

if (e == null) {

return null;

}//如果左子树不为空,则直接后继为左子节点

else if ( != null) {//先看左子节点是否为空

return ;//如果不为空,则直接后继为左子节点

}//否则如果右子树不为空,则直接后继为右子节点

else if ( != null) {//如果左子节点为空,则看右子节点是否为空

return ;//如果右子节点不为空,则返回 }//左右子节点都为空的情况下

else {

Entry s = t;

Entry c = e;

/*

* 一直向上,直到c是s的左子树,且s的右子树不为空。请试着找一下36与68节点的

* 直接后继节点,36的应该是75,而68则没有后继节点了

*

* 50

* /

* 37 75

* / /

* 25 61

* / /

* 15 30 55 68

* /

* 28 32 59

*

* 36

*/

while (s != null && (c == || == null)) {

c = s;

s = t;

}

//退出循环时 s 可以为null,比如查找 68 节点的直接后继时退出循环时s=null

if (s == null) {

return null;

} else {

return ;

}

}

}

/**

* 查找前序遍历(根左右)直接前驱节点

*

* 以非递归 右左根 的方式遍历树

*

* @param e 需要查找哪个节点的直接前驱节点

* @return Entry 前序遍历直接前驱节点

*/

public Entry preOrderAncestor(Entry e) {

if (e == null) {

return null;

}//如果节点为父节点的左节点,则父节点就是直接前驱节点

else if (t != null && e == ) {

return t;

}//如果节点为父节点的右节点

else if (t != null && e == ) {

}

Entry s = t;//前驱节点默认为父节点

if ( != null) {//如果父节点没有左子,前驱节点就为父节点

s = ;//如果父节点的左子节点不空,则初始为父节点左子节点

/*

* 只要父节点左子节点还有子节点,则前驱节点要从其子树中找。请试着 * 一下75直接前驱节点,应该是36

*

* 50

* /

* 37 75

* / /

* 25 61

* / /

* 15 30 55 68

* /

* 28 32 59

*

* 36

*/

while ( != null || != null) {

//在父节点的左子节点的子树中查找时,一定要先向右边拐

if ( != null) {

s = ;

} else {//如果右边没有,然后才能向左边拐

s = ;

}

}

}

return s;

} else {//如果是根节点,则没有直接前驱节点了

return null;

}

/**

* 查找后序遍历(左右根)直接后继节点

*

* 以非递归 左右根 的方式遍历树

*

* @param e 需要查找哪个节点的直接后继节点

* @return Entry 后序遍历直接后继节点

*/

public Entry postOrderSuccessor(Entry e) {

if (e == null) {

return null;

}//如果节点为父节点的右子节点,则父节点就是直接后继节点

else if (t != null && e == ) {

return t;

}//如果节点为父节点的左子节点

else if (t != null && e == ) {

Entry s = t;//后继节点默认为父节点

if ( != null) {//如果父节点没有右子,后继节点就为父节点

s = ;//如果父节点的右子节点不空,则初始为父节点右子节点

/*

* 只要父节点右子节点还有子节点,则后断节点要从其子树中找,

* 如15的后继节点为28

* 50

* /

* 37 75

* / /

* 25 61

* / /

* 15 30 55 68

* /

* 28 32 59

*

* 36

*/

while ( != null || != null) {

//在父节点的右子节点的子树中查找时,一定要先向左边拐

if ( != null) {

s = ;

} else {//如果左边没有,然后才能向右边拐

s = ;

}

} }

return s;

} else {

//如果是根节点,则没有后继节点了

return null;

}

}

/**

* 查找后序遍历(左右根)直接前驱节点

*

* 以非递归 根右左 的方式遍历树

*

* @param e 需要查找哪个节点的直接前驱节点

* @return Entry 后序遍历直接前驱节点

*/

public Entry postOrderAncestor(Entry e) {

if (e == null) {

return null;

}//如果右子树不为空,则直接前驱为右子节点

else if ( != null) {//先看右子节点是否为空

return ;//如果不为空,则直接后继为右子节点

}//否则如果左子树不为空,则直接前驱为左子节点

else if ( != null) {

return ;

}//左右子节点都为空的情况下

else {

Entry s = t;

Entry c = e;

/*

* 一直向上,直到c是s的右子树,且s的左子树不为空。请试着找一下59与15节点的

* 直接后继节点,59的应该是37,而15则没有后继节点了

*

* 50

* /

* 37 75

* / /

* 25 61

* / /

* 15 30 55 68

* / * 28 32 59

*

* 36

*/

while (s != null && (c == || == null)) {

c = s;

s = t;

}

if (s == null) {

return null;

} else {

return ;

}

}

}

/**

* 查找中序遍历(左根右)直接后继节点

*

* 以非递归 左根右 的方式遍历树

*

* @param e 需要查找哪个节点的直接后继节点

* @return Entry 中序遍历直接后继节点

*/

public Entry inOrderSuccessor(Entry e) {

if (e == null) {

return null;

}//如果待找的节点有右子树,则在右子树上查找

else if ( != null) {

//默认后继节点为右子节点(如果右子节点没有左子树时即为该节点)

Entry p = ;

while ( != null) {

//注,如果右子节点的左子树不为空,则在左子树中查找,且后面找时要一直向左拐

p = ;

}

return p;

}//如果待查节点没有右子树,则要在祖宗节点中查找后继节点

else {

//默认后继节点为父节点(如果待查节点为父节点的左子树,则后继为父节点)

Entry p = t;

Entry current = e;//当前节点,如果其父不为后继,则下次指向父节点

//如果待查节点为父节点的右节点时,继续向上找,一直要找到current为左子节点,则s才是后继 while (p != null && current == ) {

current = p;

p = t;

}

return p;

}

}

/**

* 查找中序遍历(左根右)直接前驱节点

*

* 以非递归 右根左 的方式遍历树

*

* @param e 需要查找哪个节点的直接前驱节点

* @return Entry 中序遍历直接前驱节点

*/

public Entry inOrderAncestor(Entry e) {

if (e == null) {

return null;

}//如果待找的节点有左子树,则在在子树上查找

else if ( != null) {

//默认直接前驱节点为左子节点(如果左子节点没有右子树时即为该节点)

Entry p = ;

while ( != null) {

//注,如果左子节点的右子树不为空,则在右子树中查找,且后面找时要一直向右拐

p = ;

}

return p;

}//如果待查节点没有左子树,则要在祖宗节点中查找前驱节点

else {

//默认前驱节点为父节点(如果待查节点为父节点的右子树,则前驱为父节点)

Entry p = t;

Entry current = e;//当前节点,如果其父不为前驱,则下次指向父节点

//如果待查节点为父节点的左节点时,继续向上找,一直要找到current为p的右子节点,则s才是前驱

while (p != null && current == ) {

current = p;

p = t;

}

return p;

}

}

/**

* 查找指定的节点

* @param num

* @return Entry

*/

public Entry getEntry(int num) {

return getEntry(root, num);

}

/**

* 使用树的先序遍历递归方式查找指定的节点

*

* @param entry

* @param num

* @return

*/

private Entry getEntry(Entry entry, int num) {

//如果找到,则停止后续搜索,并把查找到的节点返回给上层调用者

if ( == num) {//1、先与父节点比对

return entry;

}

Entry tmp = null;

if ( != null) {//2、再在左子树上找

tmp = getEntry(, num);

//如果左子树上找到,返回并停止查找,否则继续在后续节点中找

if (tmp != null) {

//节点在左子树中找到,返回给上层调用者

return tmp;

}

}

if ( != null) {//3、否则在右子树上找

tmp = getEntry(, num);

//如果右子树上找到,返回并停止查找,否则继续在后续节点中找

if (tmp != null) {

//节点在右子树中找到,返回给上层调用者

return tmp;

}

}

//当前比较节点 entry 子树为空或不为空时没有找到,直接返回给上层调用者null

}

return null;

/**

* 根据给定的数组创建一棵树,这个棵树可以是完全二叉树也可是普通二叉树

* 数组中为0的表示不创建该位置上的节点

* @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

*/

public void createBinTree(int[] nums) {

root = recurCreateBinTree(nums, null, 0);

}

/**

* 递归创建二叉树

* @param nums 数组中指定了要创建的节点的编号,如果为0,表示不创建

* @param paraent 父节点

* @param index 需要使用数组中的哪个元素创建节点,如果为元素为0,则不创建

* @return Entry 返回创建的节点,最终会返回树的根节点

*/

private Entry recurCreateBinTree(int[] nums, Entry pararent, int index) {

//指定索引上的编号不为零上才需创建节点

if (nums[index] != 0) {

size++;

Entry root = new Entry(nums[index], pararent);//根节点

//如果有左子树则创建左子树

if ((index + 1) * 2 <= ) {

= (Entry) recurCreateBinTree(nums, root, (index + 1) * 2 - 1);

//如果还可以创建右子树,则创建

if ((index + 1) * 2 + 1 <= ) {

= (Entry) recurCreateBinTree(nums, root, (index + 1) * 2);

}

}

return (Entry) root;

}

return null;

}

public int size() {

return size;

}

//测试

public static void main(String[] args) {

//创建一棵非完全二叉树

BackBinTree binTree = new BackBinTree();

/*

* 50

* /

* 37 75

* / /

* 25 61

* / /

* 15 30 55 68

* /

* 28 32 59

*

* 36

*/

int[] nums = new int[] { 50, 37, 75, 25, 0, 61, 0, 15, 30, 0, 0, 55, 68, 0, 0, 0,

0, 28, 32, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 };

BinTree(nums);

Entry entry = ry(50);

("根左右(先序遍历)- ");

while (entry != null) {

( + " ");

entry = erSuccessor(entry);

}

n();

entry = ry(68);

("右左根(先序的逆)- ");

while (entry != null) {

( + " ");

entry = erAncestor(entry);

}

n();

entry = ry(15);

("左右根(后序遍历)- ");

while (entry != null) {

( + " ");

entry = derSuccessor(entry);

}

n();

entry = ry(50);

("根右左(后序的逆)- ");

}

}

while (entry != null) {

( + " ");

entry = derAncestor(entry);

}

n();

entry = ry(15);

("左根右(中序遍历)- ");

while (entry != null) {

( + " ");

entry = rSuccessor(entry);

}

n();

entry = ry(75);

("右根左(中序的逆)- ");

while (entry != null) {

( + " ");

entry = rAncestor(entry);

}

n();

/*

* output:

* 根左右(先序遍历)- 50 37 25 15 30 28 32 36 75 61 55 59 68

* 右左根(先序的逆)- 68 59 55 61 75 36 32 28 30 15 25 37 50

* 左右根(后序遍历)- 15 28 36 32 30 25 37 59 55 68 61 75 50

* 根右左(后序的逆)- 50 75 61 68 55 59 37 25 30 32 36 28 15

* 左根右(中序遍历)- 15 25 28 30 32 36 37 50 55 59 61 68 75

* 右根左(中序的逆)- 75 68 61 59 55 50 37 36 32 30 28 25 15

*/

发布者:admin,转转请注明出处:http://www.yc00.com/web/1687384944a6091.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信