1. 程式人生 > >數據結構與算法的學習-二叉樹

數據結構與算法的學習-二叉樹

內容 例如 bin ise postorder import 它的 treenode etl

二叉樹的定義:

二叉樹是樹形結構的一個重要類型。許多實際問題抽象出來的數據結構往往是二叉樹的形式,即使是一般的樹也能簡單地轉換為二叉樹,而且二叉樹的存儲結構及其算法都較為簡單,因此二叉樹顯得特別重要。
二叉樹(BinaryTree)是n(n≥0)個結點的有限集,它或者是空集(n=0),或者由一個根結點及兩棵互不相交的、分別稱作這個根的左子樹和右子樹的二叉樹組成。
這個定義是遞歸的。由於左、右子樹也是二叉樹, 因此子樹也可為空樹。

二叉樹的遍歷

對於二叉樹來講最主要、最基本的運算是遍歷。
遍歷二叉樹 是指以一定的次序訪問二叉樹中的每個結點。所謂 訪問結點 是指對結點進行各種操作的簡稱。例如,查詢結點數據域的內容,或輸出它的值,或找出結點位置,或是執行對結點的其他操作。遍歷二叉樹的過程實質是把二叉樹的結點進行線性排列的過程。假設遍歷二叉樹時訪問結點的操作就是輸出結點數據域的值,那麽遍歷的結果得到一個線性序列。

從二叉樹的遞歸定義可知,一棵非空的二叉樹由根結點及左、右子樹這三個基本部分組成。因此,在任一給定結點上,可以按某種次序執行三個操作:
 (1)訪問結點本身(N),
 (2)遍歷該結點的左子樹(L),
 (3)遍歷該結點的右子樹(R)。
以上三種操作有六種執行次序:
 NLR、LNR、LRN、NRL、RNL、RLN。
註意:
前三種次序與後三種次序對稱,故只討論先左後右的前三種次序。
  由於被訪問的結點必是某子樹的根,所以N(Node)、L(Left subtlee)和R(Right subtree)又可解釋為根、根的左子樹和根的右子樹。NLR、LNR和LRN分別又稱為先根遍歷、中根遍歷和後根遍歷。

二叉樹的java實現

java實現代碼:

[java] package study_02.datastructure.tree;
  1. import java.util.Stack;
  2. /**
  3. * 二叉樹的鏈式存儲
  4. * @author WWX
  5. */
  6. public class BinaryTree {
  7. private TreeNode root=null;
  8. public BinaryTree(){
  9. root=new TreeNode(1,"rootNode(A)");
  10. }
  11. /**
  12. * 創建一棵二叉樹
  13. * <pre>
  14. * A
  15. * B C
  16. * D E F
  17. * </pre>
  18. * @param root
  19. * @author WWX
  20. */
  21. public void createBinTree(TreeNode root){
  22. TreeNode newNodeB = new TreeNode(2,"B");
  23. TreeNode newNodeC = new TreeNode(3,"C");
  24. TreeNode newNodeD = new TreeNode(4,"D");
  25. TreeNode newNodeE = new TreeNode(5,"E");
  26. TreeNode newNodeF = new TreeNode(6,"F");
  27. root.leftChild=newNodeB;
  28. root.rightChild=newNodeC;
  29. root.leftChild.leftChild=newNodeD;
  30. root.leftChild.rightChild=newNodeE;
  31. root.rightChild.rightChild=newNodeF;
  32. }
  33. public boolean isEmpty(){
  34. return root==null;
  35. }
  36. //樹的高度
  37. public int height(){
  38. return height(root);
  39. }
  40. //節點個數
  41. public int size(){
  42. return size(root);
  43. }
  44. private int height(TreeNode subTree){
  45. if(subTree==null)
  46. return 0;//遞歸結束:空樹高度為0
  47. else{
  48. int i=height(subTree.leftChild);
  49. int j=height(subTree.rightChild);
  50. return (i<j)?(j+1):(i+1);
  51. }
  52. }
  53. private int size(TreeNode subTree){
  54. if(subTree==null){
  55. return 0;
  56. }else{
  57. return 1+size(subTree.leftChild)
  58. +size(subTree.rightChild);
  59. }
  60. }
  61. //返回雙親結點
  62. public TreeNode parent(TreeNode element){
  63. return (root==null|| root==element)?null:parent(root, element);
  64. }
  65. public TreeNode parent(TreeNode subTree,TreeNode element){
  66. if(subTree==null)
  67. return null;
  68. if(subTree.leftChild==element||subTree.rightChild==element)
  69. //返回父結點地址
  70. return subTree;
  71. TreeNode p;
  72. //現在左子樹中找,如果左子樹中沒有找到,才到右子樹去找
  73. if((p=parent(subTree.leftChild, element))!=null)
  74. //遞歸在左子樹中搜索
  75. return p;
  76. else
  77. //遞歸在右子樹中搜索
  78. return parent(subTree.rightChild, element);
  79. }
  80. public TreeNode getLeftChildNode(TreeNode element){
  81. return (element!=null)?element.leftChild:null;
  82. }
  83. public TreeNode getRightChildNode(TreeNode element){
  84. return (element!=null)?element.rightChild:null;
  85. }
  86. public TreeNode getRoot(){
  87. return root;
  88. }
  89. //在釋放某個結點時,該結點的左右子樹都已經釋放,
  90. //所以應該采用後續遍歷,當訪問某個結點時將該結點的存儲空間釋放
  91. public void destroy(TreeNode subTree){
  92. //刪除根為subTree的子樹
  93. if(subTree!=null){
  94. //刪除左子樹
  95. destroy(subTree.leftChild);
  96. //刪除右子樹
  97. destroy(subTree.rightChild);
  98. //刪除根結點
  99. subTree=null;
  100. }
  101. }
  102. public void traverse(TreeNode subTree){
  103. System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
  104. traverse(subTree.leftChild);
  105. traverse(subTree.rightChild);
  106. }
  107. //前序遍歷
  108. public void preOrder(TreeNode subTree){
  109. if(subTree!=null){
  110. visted(subTree);
  111. preOrder(subTree.leftChild);
  112. preOrder(subTree.rightChild);
  113. }
  114. }
  115. //中序遍歷
  116. public void inOrder(TreeNode subTree){
  117. if(subTree!=null){
  118. inOrder(subTree.leftChild);
  119. visted(subTree);
  120. inOrder(subTree.rightChild);
  121. }
  122. }
  123. //後續遍歷
  124. public void postOrder(TreeNode subTree) {
  125. if (subTree != null) {
  126. postOrder(subTree.leftChild);
  127. postOrder(subTree.rightChild);
  128. visted(subTree);
  129. }
  130. }
  131. //前序遍歷的非遞歸實現
  132. public void nonRecPreOrder(TreeNode p){
  133. Stack<TreeNode> stack=new Stack<TreeNode>();
  134. TreeNode node=p;
  135. while(node!=null||stack.size()>0){
  136. while(node!=null){
  137. visted(node);
  138. stack.push(node);
  139. node=node.leftChild;
  140. }
  141. <span abp="507" style="font-size:14px;">while</span>(stack.size()>0){
  142. node=stack.pop();
  143. node=node.rightChild;
  144. }
  145. }
  146. }
  147. //中序遍歷的非遞歸實現
  148. public void nonRecInOrder(TreeNode p){
  149. Stack<TreeNode> stack =new Stack<BinaryTree.TreeNode>();
  150. TreeNode node =p;
  151. while(node!=null||stack.size()>0){
  152. //存在左子樹
  153. while(node!=null){
  154. stack.push(node);
  155. node=node.leftChild;
  156. }
  157. //棧非空
  158. if(stack.size()>0){
  159. node=stack.pop();
  160. visted(node);
  161. node=node.rightChild;
  162. }
  163. }
  164. }
  165. //後序遍歷的非遞歸實現
  166. public void noRecPostOrder(TreeNode p){
  167. Stack<TreeNode> stack=new Stack<BinaryTree.TreeNode>();
  168. TreeNode node =p;
  169. while(p!=null){
  170. //左子樹入棧
  171. for(;p.leftChild!=null;p=p.leftChild){
  172. stack.push(p);
  173. }
  174. //當前結點無右子樹或右子樹已經輸出
  175. while(p!=null&&(p.rightChild==null||p.rightChild==node)){
  176. visted(p);
  177. //紀錄上一個已輸出結點
  178. node =p;
  179. if(stack.empty())
  180. return;
  181. p=stack.pop();
  182. }
  183. //處理右子樹
  184. stack.push(p);
  185. p=p.rightChild;
  186. }
  187. }
  188. public void visted(TreeNode subTree){
  189. subTree.isVisted=true;
  190. System.out.println("key:"+subTree.key+"--name:"+subTree.data);;
  191. }
  192. /**
  193. * 二叉樹的節點數據結構
  194. * @author WWX
  195. */
  196. private class TreeNode{
  197. private int key=0;
  198. private String data=null;
  199. private boolean isVisted=false;
  200. private TreeNode leftChild=null;
  201. private TreeNode rightChild=null;
  202. public TreeNode(){}
  203. /**
  204. * @param key 層序編碼
  205. * @param data 數據域
  206. */
  207. public TreeNode(int key,String data){
  208. this.key=key;
  209. this.data=data;
  210. this.leftChild=null;
  211. this.rightChild=null;
  212. }
  213. }
  214. //測試
  215. public static void main(String[] args) {
  216. BinaryTree bt = new BinaryTree();
  217. bt.createBinTree(bt.root);
  218. System.out.println("the size of the tree is " + bt.size());
  219. System.out.println("the height of the tree is " + bt.height());
  220. System.out.println("*******(前序遍歷)[ABDECF]遍歷*****************");
  221. bt.preOrder(bt.root);
  222. System.out.println("*******(中序遍歷)[DBEACF]遍歷*****************");
  223. bt.inOrder(bt.root);
  224. System.out.println("*******(後序遍歷)[DEBFCA]遍歷*****************");
  225. bt.postOrder(bt.root);
  226. System.out.println("***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************");
  227. bt.nonRecPreOrder(bt.root);
  228. System.out.println("***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************");
  229. bt.nonRecInOrder(bt.root);
  230. System.out.println("***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************");
  231. bt.noRecPostOrder(bt.root);
  232. }
  233. }
  234. </span>

輸出結果

the size of the tree is 6
the height of the tree is 3
*******(前序遍歷)[ABDECF]遍歷*****************
key:1--name:rootNode(A)
key:2--name:B
key:4--name:D
key:5--name:E
key:3--name:C
key:6--name:F
*******(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:rootNode(A)
key:3--name:C
key:6--name:F
*******(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:rootNode(A)
***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************
key:1--name:rootNode(A)
key:2--name:B
key:4--name:D
key:5--name:E
key:3--name:C
key:6--name:F
***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:rootNode(A)
key:3--name:C
key:6--name:F
***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:rootNode(A)

數據結構與算法的學習-二叉樹