暑期实习面试准备--数据结构

数据结构

数据结构

链表

  • 链表是一种由节点(Node)组成的线性数据集合,每个节点通过指针指向下一个节点。它是一种由节点组成,并能用于表示序列的数据结构。
  • 单链表:每个节点仅指向下一个节点,最后一个节点指向空(null)。
  • 双链表:每个节点有两个指针p,n。p指向前一个节点,n指向下一个节点;最后一个节点指向空。
  • 循环链表:每个节点指向下一个节点,最后一个节点指向第一个节点。
  • 时间复杂度:
    • 索引:O(n)
    • 查找:O(n)
    • 插入:O(1)
    • 删除:O(1)

  • 栈是一个元素集合,支持两个基本操作:push用于将元素压入栈,pop用于删除栈顶元素。
  • 后进先出的数据结构(Last In First Out, LIFO)
  • 时间复杂度
    • 索引:O(n)
    • 查找:O(n)
    • 插入:O(1)
    • 删除:O(1)

队列

  • 队列是一个元素集合,支持两种基本操作:enqueue 用于添加一个元素到队列,dequeue 用于删除队列中的一个元素。
  • 先进先出的数据结构(First In First Out, FIFO)。
  • 时间复杂度
    • 索引:O(n)
    • 查找:O(n)
    • 插入:O(1)
    • 删除:O(1)

  • 树是无向、联通的无环图。

B-树




b+树



二叉树

  • 二叉树是一个树形数据结构,每个节点最多可以有两个子节点,称为左子节点和右子节点。
  • 满二叉树(Full Tree):二叉树中的每个节点有 0 或者 2 个子节点。
  • 完美二叉树(Perfect Binary):二叉树中的每个节点有两个子节点,并且所有的叶子节点的深度是一样的。
  • 完全二叉树:二叉树中除最后一层外其他各层的节点数均达到最大值,最后一层的节点都连续集中在最左边。

二叉查找树

  • 二叉查找树(BST)是一种二叉树。其任何节点的值都大于等于左子树中的值,小于等于右子树中的值。
  • 时间复杂度
    • 索引:O(log(n))
    • 查找:O(log(n))
    • 插入:O(log(n))
    • 删除:O(log(n))

字典树

  • 字典树,又称为基数树或前缀树,是一种用于存储键值为字符串的动态集合或关联数组的查找树。树中的节点并不直接存储关联键值,而是该节点在树中的位置决定了其关联键值。一个节点的所有子节点都有相同的前缀,根节点则是空字符串。

树状数组

  • 树状数组,又称为二进制索引树(Binary Indexed Tree,BIT),其概念上是树,但以数组实现。数组中的下标代表树中的节点,每个节点的父节点或子节点的下标可以通过位运算获得。数组中的每个元素都包含了预计算的区间值之和,在整个树更新的过程中,这些计算的值也同样会被更新。
  • 时间复杂度
    • 区间求和:O(log(n))
    • 更新:O(log(n))

线段树

  • 线段树是用于存储区间和线段的树形数据结构。它允许查找一个节点在若干条线段中出现的次数。
  • 时间复杂度
    • 区间查找:O(log(n))
    • 更新:O(log(n))

  • 堆是一种基于树的满足某些特性的数据结构:整个堆中的所有父子节点的键值都满足相同的排序条件。堆分为最大堆和最小堆。在最大堆中,父节点的键值永远大于等于所有子节点的键值,根节点的键值是最大的。最小堆中,父节点的键值永远小于等于所有子节点的键值,根节点的键值是最小的。
  • 时间复杂度
    • 索引:O(log(n))
    • 查找:O(log(n))
    • 插入:O(log(n))
    • 删除:O(log(n))
    • 删除最大值/最小值:O(1)

哈希

  • 哈希用于将任意长度的数据映射到固定长度的数据。哈希函数的返回值被称为哈希值、哈希码或者哈希。如果不同的主键得到相同的哈希值,则发生了冲突。
  • Hash Maphash map 是一个存储键值间关系的数据结构。HashMap 通过哈希函数将键转化为桶或者槽中的下标,从而便于指定值的查找。
  • 冲突解决
    • 链地址法(Separate Chaining):在链地址法中,每个桶(bucket)是相互独立的,每一个索引对应一个元素列表。处理HashMap 的时间就是查找桶的时间(常量)与遍历列表元素的时间之和。
    • 开放地址法(Open Addressing):在开放地址方法中,当插入新值时,会判断该值对应的哈希桶是否存在,如果存在则根据某种算法依次选择下一个可能的位置,直到找到一个未被占用的地址。开放地址即某个元素的位置并不永远由其哈希值决定。

  • 图是G =(V,E)的有序对,其包括顶点或节点的集合 V 以及边或弧的集合E,其中E包括了两个来自V的元素(即边与两个顶点相关联 ,并且该关联为这两个顶点的无序对)。
  • 无向图:图的邻接矩阵是对称的,因此如果存在节点 u 到节点 v 的边,那节点 v 到节点 u 的边也一定存在。
  • 有向图:图的邻接矩阵不是对称的。因此如果存在节点 u 到节点 v 的边并不意味着一定存在节点 v 到节点 u 的边。


排序


希尔排序

不稳定

最好:onlogn

最差:o2

public static void shellSortSmallToBig(int[] data) {

int j = 0;

int temp = 0;

for (int increment = data.length / 2; increment > 0; increment /= 2) {

System.out.println("increment:" + increment);

for (int i = increment; i < data.length; i++) {

// System.out.println("i:" + i);

temp = data[i];

for (j = i - increment; j >= 0; j -= increment) {

// System.out.println("j:" + j);

// System.out.println("temp:" + temp);

// System.out.println("data[" + j + "]:" + data[j]);

if (temp < data[j]) {

data[j + increment] = data[j];

} else {

break;

}

}

data[j + increment] = temp;

}

for (int i = 0; i < data.length; i++)

System.out.print(data[i] + " "); }

}

public static void main(String[] args) {

int[] data = new int[] { 26, 53, 67, 48, 57, 13, 48, 32, 60, 50 };

shellSortSmallToBig(data);

System.out.println(Arrays.toString(data));

}

快速排序

  • 稳定:否
  • 时间复杂度
    • 最优:O(nlog(n))
    • 最差:O(n^2)
    • 平均:O(nlog(n)

public static int partition(int []array,int lo,int hi){
        //固定的切分方式
        int key=array[lo];
        while(lo<hi){
            while(array[hi]>=key&&hi>lo){//从后半部分向前扫描
                hi--;
            }
            array[lo]=array[hi];
            while(array[lo]<=key&&hi>lo){从前半部分向后扫描
                lo++;
            }
            array[hi]=array[lo];
        }
        array[hi]=key;
        return hi;
    }
    
    public static void sort(int[] array,int lo ,int hi){
        if(lo>=hi){
            return ;
        }
        int index=partition(array,lo,hi);
        sort(array,lo,index-1);
        sort(array,index+1,hi); 
    }

合并排序

  • 合并排序是一种分治算法。这个算法不断地将一个数组分为两部分,分别对左子数组和右子数组排序,然后将两个数组合并为新的有序数组。
  • 稳定:是
  • 时间复杂度:
    • 最优:O(nlog(n))
    • 最差:O(nlog(n))
    • 平均:O(nlog(n))

桶排序

  • 桶排序是一种将元素分到一定数量的桶中的排序算法。每个桶内部采用其他算法排序,或递归调用桶排序。
  • 时间复杂度
    • 最优:Ω(n + k)
    • 最差: O(n^2)
    • 平均:Θ(n + k)

基数排序

  • 基数排序类似于桶排序,将元素分发到一定数目的桶中。不同的是,基数排序在分割元素之后没有让每个桶单独进行排序,而是直接做了合并操作。
  • 时间复杂度
    • 最优:Ω(nk)
    • 最差: O(nk)
    • 平均:Θ(nk)

图算法

深度优先搜索

  • 深度优先搜索是一种先遍历子节点而不回溯的图遍历算法。
  • 时间复杂度:O(|V| + |E|)

广度优先搜索

  • 广度优先搜索是一种先遍历邻居节点而不是子节点的图遍历算法。
  • 时间复杂度:O(|V| + |E|)

拓扑排序

  • 拓扑排序是有向图节点的线性排序。对于任何一条节点 u 到节点 v 的边,u 的下标先于 v。
  • 时间复杂度:O(|V| + |E|)

Dijkstra算法

  • Dijkstra 算法是一种在有向图中查找单源最短路径的算法。
  • 时间复杂度:O(|V|^2)

public  class  Dijkstra {
 
     private  static  int  N =  1000 ;
     private  static  int [][] Graph = {
             0 1 5 , N, N, N, N, N, N },
             1 0 3 7 5 , N, N, N, N },
             5 3 0 , N,  1 7 , N, N, N },
             { N,  7 , N,  0 2 , N,  3 , N, N },
             { N,  5 1 2 0 3 6 9 , N },
             { N, N,  7 , N,  3 0 , N,  5 , N },
             { N, N, N,  3 6 , N,  0 2 7  },
             { N, N, N, N,  9 5 2 0 4  },
             { N, N, N, N, N, N,  7 4 0  } };
 
     public  static  void  main(String[] args) {
         dijkstra( 0 , Graph);
     }
 
     /**
      * Dijkstra最短路径。
      * 即图中"节点vs"到其它各个节点的最短路径。
      * @param vs 起始节点
      * @param Graph 图
      */
     public  static  void  dijkstra( int  vs,  int [][] Graph) {
         int  NUM = Graph[ 0 ].length;
         // 前驱节点数组
         int [] prenode =  new  int [NUM];
         // 最短距离数组
         int [] mindist =  new  int [NUM];
         // 该节点是否已经找到最短路径
         boolean [] find =  new  boolean [NUM];
         
         int  vnear =  0 ;
         
         for  ( int  i =  0 ; i < mindist.length; i++) {
             prenode[i] = i;
             mindist[i] = Graph[vs][i];
             find[i] =  false ;
         }
 
         find[vs] =  true ;
 
         for  ( int  v =  1 ; v < Graph.length; v++) {
 
             // 每次循环求得距离vs最近的节点vnear和最短距离min
             int  min = N;
             for  ( int  j =  0 ; j < Graph.length; j++) {
                 if  (!find[j] && mindist[j] < min) {
                     min = mindist[j];
                     vnear = j;
                 }
             }
             find[vnear] =  true ;
 
             // 根据vnear修正vs到其他所有节点的前驱节点及距离
             for  ( int  k =  0 ; k < Graph.length; k++) {
                 if  (!find[k] && (min + Graph[vnear][k]) < mindist[k]) {
                     prenode[k] = vnear;
                     mindist[k] = min + Graph[vnear][k];
                 }
             }
         }
         
         for  ( int  i =  0 ; i < NUM; i++) {
             System.out.println( "v"  + vs +  "...v"  + prenode[i] +  "->v"  + i +  ", s="  + mindist[i]);
         }
     }


Bellman-Ford算法

  • Bellman-Ford 是一种在带权图中查找单一源点到其他节点最短路径的算法。
  • 虽然时间复杂度大于 Dijkstra 算法,但它可以处理包含了负值边的图。
  • 时间复杂度:
    • 最优:O(|E|)
    • 最差:O(|V||E|)

Floyd-Warshall 算法

  • Floyd-Warshall 算法是一种在无环带权图中寻找任意节点间最短路径的算法。
  • 该算法执行一次即可找到所有节点间的最短路径(路径权重和)。
  • 时间复杂度:
    • 最优:O(|V|^3)
    • 最差:O(|V|^3)
    • 平均:O(|V|^3)

最小生成树算法

  • 最小生成树算法是一种在无向带权图中查找最小生成树的贪心算法。换言之,最小生成树算法能在一个图中找到连接所有节点的边的最小子集。
  • 时间复杂度:O(|V|^2)


  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         int MAX = Integer.MAX_VALUE;  
  4.         int[][] map = new int[][]{  
  5.             {0,10,MAX,MAX,MAX,11,MAX,MAX,MAX},  
  6.             {10,0,18,MAX,MAX,MAX,16,MAX,12},  
  7.             {MAX,MAX,0,22,MAX,MAX,MAX,MAX,8},  
  8.             {MAX,MAX,22,0,20,MAX,MAX,16,21},  
  9.             {MAX,MAX,MAX,20,0,26,MAX,7,MAX},  
  10.             {11,MAX,MAX,MAX,26,0,17,MAX,MAX},  
  11.             {MAX,16,MAX,MAX,MAX,17,0,19,MAX},  
  12.             {MAX,MAX,MAX,16,7,MAX,19,0,MAX},  
  13.             {MAX,12,8,21,MAX,MAX,MAX,MAX,0}  
  14.         };  
  15.         int sum = prim(map);  
  16.         System.out.println(sum);  
  17.     }  
  18.     public static int prim(int[][] arr){  
  19.         //统计最小的权  
  20.         int sum = 0;  
  21.         //当前最小生成树所能到达的顶点的最小权数组  
  22.         int[] costs = new int[9];  
  23.         //当前各个顶点对应的起点  
  24.         int[] startPoint = new int[9];  
  25.         //初始化  
  26.         for(int i =1;i<9;i++){  
  27.             //所有点的起点赋值为0  
  28.             startPoint[i] = 0;  
  29.             //以0为起点到达各个顶点的权值  
  30.             costs[i] = arr[0][i];  
  31.         }  
  32.         //挑选剩余的8个顶点  
  33.         for(int i = 1;i<9;i++){  
  34.             //记录当前costs里面的最小权值是多少  
  35.             int min = Integer.MAX_VALUE;  
  36.             //记录当前costs里面的最小权值对应的数组下标,即顶点  
  37.             //(数组[顶点]=该顶点对应的起点)  
  38.             int minIndex = 0;  
  39.             //遍历costs  
  40.             for(int j=1;j<9;j++){  
  41.                 int temp = costs[j];  
  42.                 //costs[j]==0代表节点j已加入MST  
  43.                 if(temp!=0&&temp < min){  
  44.                     min = temp;  
  45.                     minIndex = j;  
  46.                 }  
  47.             }  
  48.             sum+=min;  
  49.             //将已加入MST的对应的权值赋值为0  
  50.             costs[minIndex] = 0;  
  51.             //选定了新的顶点到MST后,树到达各顶点的最小开销和起点将更新  
  52.             //更新costs和startPoint  
  53.             for(int k=0;k<9;k++){  
  54.                 //用minIndex顶点到各个顶点的权值比较costs数组的值,若较小则替换,并更新起点为minIndex  
  55.                 int newCost = arr[minIndex][k];  
  56.                 if(newCost!=0&&newCost<costs[k]){  
  57.                     costs[k] = newCost;  
  58.                     //更新K的起点为minIndex  
  59.                     startPoint[k] = minIndex;  
  60.                 }  
  61.             }  
  62.         }  
  63.         return sum;  
  64.     }  
  65. }  

Kruskal 算法

  • Kruskal 算法也是一个计算最小生成树的贪心算法,但在 Kruskal 算法中,图不一定是连通的。
  • 时间复杂度:O(|E|log|V|)


求环路

public class Solution {

ListNode EntryNodeOfLoop(ListNode h){

if(h == null || h.next == null)

return null;

ListNode slow = h;

ListNode fast = h;

while(fast != null && fast.next != null ){

slow = slow.next;

fast = fast.next.next;

if(slow == fast){

ListNode p=h;

ListNode q=slow;//相当于让q指向了m1

while(p != q){

p = p.next;

q = q.next;

}

if(p == q)

return q;

}

}

return null;

}

位运算

  • 位运算即在比特级别进行操作的技术。使用位运算技术可以带来更快的运行速度与更小的内存使用。
  • 测试第 k 位:s & (1 << k);
  • 设置第k位:s |= (1 << k);
  • 关闭第k位:s &= ~(1 << k);
  • 切换第k位:s ^= (1 << k);
  • 乘以2n:s << n;
  • 除以2n:s >> n;
  • 交集:s & t;
  • 并集:s | t;
  • 减法:s & ~t;
  • 提取最小非0位:s & (-s);
  • 提取最小0位:~s & (s + 1);
  • 交换值:x ^= y; y ^= x; x ^= y;

树算法

树的递归和非递归遍历

  1. import java.util.Stack;  
  2. public class BinaryTree {  
  3.     protected Node root;    
  4.         
  5.     public BinaryTree(Node root) {    
  6.         this.root = root;    
  7.     }    
  8.     
  9.     public Node getRoot() {    
  10.         return root;    
  11.     }    
  12.     
  13.     /** 构造树 */    
  14.     public static Node init() {    
  15.         Node a = new Node('A');    
  16.         Node b = new Node('B'null, a);    
  17.         Node c = new Node('C');    
  18.         Node d = new Node('D', b, c);    
  19.         Node e = new Node('E');    
  20.         Node f = new Node('F', e, null);    
  21.         Node g = new Node('G'null, f);    
  22.         Node h = new Node('H', d, g);    
  23.         return h;// root    
  24.     }    
  25.     
  26.     /** 访问节点 */    
  27.     public static void visit(Node p) {    
  28.         System.out.print(p.getKey() + " ");    
  29.     }    
  30.     
  31.     /** 递归实现前序遍历 */    
  32.     protected static void preorder(Node p) {    
  33.         if (p != null) {    
  34.             visit(p);    
  35.             preorder(p.getLeft());    
  36.             preorder(p.getRight());    
  37.         }    
  38.     }    
  39.     
  40.     /** 递归实现中序遍历 */    
  41.     protected static void inorder(Node p) {    
  42.         if (p != null) {    
  43.             inorder(p.getLeft());    
  44.             visit(p);    
  45.             inorder(p.getRight());    
  46.         }    
  47.     }    
  48.     
  49.     /** 递归实现后序遍历 */    
  50.     protected static void postorder(Node p) {    
  51.         if (p != null) {    
  52.             postorder(p.getLeft());    
  53.             postorder(p.getRight());    
  54.             visit(p);    
  55.         }    
  56.     }    
  57.   /**********************************************************************************************/  
  58.     /** 非递归实现前序遍历 */    
  59.     protected static void iterativePreorder(Node p) {    
  60.         Stack<Node> stack = new Stack<Node>();    
  61.         if (p != null) {    
  62.             stack.push(p);    
  63.             while (!stack.empty()) {    
  64.                 p = stack.pop();    
  65.                 visit(p);    
  66.                 if (p.getRight() != null)    
  67.                     stack.push(p.getRight());    
  68.                 if (p.getLeft() != null)  //为什么p.getLeft() 在后,getRight()在前应为while 循环第一句就是pop visit所以要把left放上,先访问。之中方法是即压即访问法。  
  69.                     stack.push(p.getLeft());    
  70.             }    
  71.         }    
  72.     }    
  73.       
  74.     /** 非递归实现中序遍历 */  //思路与上面iterativePreorder 一致。  
  75.     protected static void iterativeInorder(Node p) {    
  76.         Stack<Node> stack = new Stack<Node>();    
  77.         while (p != null) {    
  78.             while (p != null) {    
  79.                 if (p.getRight() != null)    
  80.                     stack.push(p.getRight());// 当前节点右子入栈    
  81.                     stack.push(p);// 当前节点入栈    
  82.                     p = p.getLeft();    
  83.             }    
  84.             p = stack.pop();    
  85.             while (!stack.empty() && p.getRight() == null) {    
  86.                 visit(p);    
  87.                 p = stack.pop();    
  88.             }    
  89.             visit(p);    
  90.             if (!stack.empty())    
  91.                 p = stack.pop();    
  92.             else    
  93.                 p = null;    
  94.         }    
  95.     }  
  96.   
  97. /*******************************************************************************************/  
  98.       
  99. /*******************************************************************************************/    
  100.     /** 非递归实现前序遍历2 */    
  101.     protected static void iterativePreorder2(Node p) {    
  102.         Stack<Node> stack = new Stack<Node>();    
  103.         Node node = p;    
  104.         while (node != null || stack.size() > 0) {    
  105.             while (node != null) {//压入所有的左节点,压入前访问它。左节点压入完后pop访问右节点。像这样算法时思考规律性的东西在哪。不管哪个节点都要压所节点判断右节点。    
  106.                 visit(node);    
  107.                 stack.push(node);    
  108.                 node = node.getLeft();    
  109.             }    
  110.             if (stack.size() > 0) {//    
  111.                 node = stack.pop();    
  112.                 node = node.getRight();    
  113.             }    
  114.         }    
  115.     }    
  116.       
  117.     /** 非递归实现中序遍历2 */    
  118.     protected static void iterativeInorder2(Node p) {    
  119.         Stack<Node> stack = new Stack<Node>();    
  120.         Node node = p;    
  121.         while (node != null || stack.size() > 0) {    
  122.             while (node != null) {    
  123.                 stack.push(node);    
  124.                 node = node.getLeft();    
  125.             }    
  126.             if (stack.size() > 0) {    
  127.                 node = stack.pop();    
  128.                 visit(node);   //与iterativePreorder2比较只有这句话的位置不一样,弹出时再访问。  
  129.                 node = node.getRight();    
  130.             }    
  131.         }    
  132.     }  
  133.       
  134.  /*******************************************************************************************/  
  135.     
  136.     /** 非递归实现后序遍历 */    
  137.     protected static void iterativePostorder(Node p) {    
  138.         Node q = p;    
  139.         Stack<Node> stack = new Stack<Node>();    
  140.         while (p != null) {    
  141.             // 左子树入栈    
  142.             for (; p.getLeft() != null; p = p.getLeft())    
  143.                 stack.push(p);    
  144.             // 当前节点无右子或右子已经输出    
  145.             while (p != null && (p.getRight() == null || p.getRight() == q)) {    
  146.                 visit(p);    
  147.                 q = p;// 记录上一个已输出节点    
  148.                 if (stack.empty())    
  149.                     return;    
  150.                 p = stack.pop();    
  151.             }    
  152.             // 处理右子    
  153.             stack.push(p);    
  154.             p = p.getRight();    
  155.         }    
  156.     }    
  157.     
  158.     /** 非递归实现后序遍历 双栈法 */    
  159.     protected static void iterativePostorder2(Node p) {//理解左子树   右子树 根递归性质,把它运用到循环当中去。    
  160.         Stack<Node> lstack = new Stack<Node>();//左子树栈    
  161.         Stack<Node> rstack = new Stack<Node>();//右子树栈  
  162.         Node node = p, right;    
  163.         do {    
  164.             while (node != null) {    
  165.                 right = node.getRight();    
  166.                 lstack.push(node);    
  167.                 rstack.push(right);    
  168.                 node = node.getLeft();    
  169.             }    
  170.             node = lstack.pop();    
  171.             right = rstack.pop();    
  172.             if (right == null) {    
  173.                 visit(node);    
  174.             } else {    
  175.                 lstack.push(node);    
  176.                 rstack.push(null);    
  177.             }    
  178.             node = right;    
  179.         } while (lstack.size() > 0 || rstack.size() > 0);    
  180.     }    
  181.     
  182.     /** 非递归实现后序遍历 单栈法*/    
  183.     protected static void iterativePostorder3(Node p) {    
  184.         Stack<Node> stack = new Stack<Node>();    
  185.         Node node = p, prev = p;    
  186.         while (node != null || stack.size() > 0) {    
  187.             while (node != null) {    
  188.                 stack.push(node);    
  189.                 node = node.getLeft();    
  190.             }    
  191.             if (stack.size() > 0) {    
  192.                 Node temp = stack.peek().getRight();    
  193.                 if (temp == null || temp == prev) {    
  194.                     node = stack.pop();    
  195.                     visit(node);    
  196.                     prev = node;    
  197.                     node = null;    
  198.                 } else {    
  199.                     node = temp;    
  200.                 }    
  201.             }    
  202.     
  203.         }    
  204.     }    
  205.     
  206.     /** 非递归实现后序遍历4 双栈法*/    
  207.     protected static void iterativePostorder4(Node p) {    
  208.         Stack<Node> stack = new Stack<Node>();    
  209.         Stack<Node> temp = new Stack<Node>();    
  210.         Node node = p;    
  211.         while (node != null || stack.size() > 0) {    
  212.             while (node != null) {    
  213.                 temp.push(node);    
  214.                 stack.push(node);    
  215.                 node = node.getRight();    
  216.             }    
  217.             if (stack.size() > 0) {    
  218.                 node = stack.pop();    
  219.                 node = node.getLeft();    
  220.             }    
  221.         }    
  222.         while (temp.size() > 0) {//把插入序列都插入到了temp。  
  223.             node = temp.pop();    
  224.             visit(node);    
  225.         }    
  226.     }    
  227.     
  228.     /**  
  229.      * @param args  
  230.      */    
  231.     public static void main(String[] args) {    
  232.         BinaryTree tree = new BinaryTree(init());   
  233.         System.out.print(" 递归遍历 \n");    
  234.         System.out.print(" Pre-Order:");    
  235.         preorder(tree.getRoot());    
  236.            
  237.         System.out.print(" \n In-Order:");    
  238.         inorder(tree.getRoot());  
  239.           
  240.         System.out.print("\n Post-Order:");    
  241.         postorder(tree.getRoot());    
  242.           
  243.         System.out.print(" \n非递归遍历");  
  244.         System.out.print(" \n Pre-Order:");    
  245.         iterativePreorder(tree.getRoot());    
  246.           
  247.         System.out.print("\n Pre-Order2:");    
  248.         iterativePreorder2(tree.getRoot());    
  249.            
  250.         System.out.print(" \n In-Order:");    
  251.         iterativeInorder(tree.getRoot());  
  252.           
  253.         System.out.print("\n In-Order2:");    
  254.         iterativeInorder2(tree.getRoot());    
  255.           
  256.         System.out.print("\n Post-Order:");    
  257.         iterativePostorder(tree.getRoot());    
  258.          
  259.         System.out.print("\n Post-Order2:");    
  260.         iterativePostorder2(tree.getRoot());    
  261.            
  262.         System.out.print("\n Post-Order3:");    
  263.         iterativePostorder3(tree.getRoot());    
  264.            
  265.         System.out.print("\n Post-Order4:");    
  266.         iterativePostorder4(tree.getRoot());    
  267.         
  268.     
  269.     }    
  270.   
  271. }  
  272.    
  273.   
  274. class Node {    
  275.     private char key;    
  276.     private Node left, right;    
  277.     
  278.     public Node(char key) {    
  279.         this(key, nullnull);    
  280.     }    
  281.     
  282.     public Node(char key, Node left, Node right) {    
  283.         this.key = key;    
  284.         this.left = left;    
  285.         this.right = right;    
  286.     }    
  287.     
  288.     public char getKey() {    
  289.         return key;    
  290.     }    
  291.     
  292.     public void setKey(char key) {    
  293.         this.key = key;    
  294.     }    
  295.     
  296.     public Node getLeft() {    
  297.         return left;    
  298.     }    
  299.     
  300.     public void setLeft(Node left) {    
  301.         this.left = left;    
  302.     }    
  303.     
  304.     public Node getRight() {    
  305.         return right;    
  306.     }    
  307.     
  308.     public void setRight(Node right) {    
  309.         this.right = right;    
  310.     }    
  311. }    



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值