Skip to content

Latest commit

 

History

History
423 lines (351 loc) · 13.6 KB

数据结构与算法.md

File metadata and controls

423 lines (351 loc) · 13.6 KB

数据结构与算法

1. 数组结构

1.1 数组/队列

1.2 单链表

1.3 双链表

1.4 Hash 表

1.5 树

1.6 图

2. 算法设计

关于复杂度

时间复杂度

如何计算时间复杂度

常见复杂度的计算时间级别

空间复杂度

如何计算控件复杂度

搜索

排序

各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。

查找问题

  1. 查找有无
  2. 查找其他

问题

排序

  1. 冒泡排序

    /**  
     *  冒泡法排序   
     *  比较相邻的元素。如果第一个比第二个小,就交换他们两个。 
     *  对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最小的数。   
     *  针对所有的元素重复以上的步骤,除了最后一个。  
     *  持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 
    
     *   
     * @param numbers  
     *            需要排序的整型数组  
     */  
    public static void bubbleSort(int[] a) {
        int temp;
        int size = a.length;
        for(int i=1; i<size; i++) {
            for(int j=0; j<size-i; j++) {
                if(a[j] < a[j+1]) {
                    temp = a[j];
                    a[j]=a[j+1];
                    a[j+1]=temp;
                }
            }
            for(int aa : a)
                System.out.print(aa+",");
            System.out.println();
        }
    }
  2. 快速排序

    /**  
     * 快速排序 
     *    
     *  从数列中挑出一个元素,称为“基准”  
     *  重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,  
     *  该基准是它的最后位置。这个称为分割(partition)操作。  
     *  递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。  
     *  
     * @param numbers  
     * @param start  
     * @param end  
     */  
    public static void quickSort(int[] numbers, int start, int end) {   
        if (start < end) {   
            int base = numbers[start]; // 选定的基准值(第一个数值作为基准值)   
            int temp; // 记录临时中间值   
            int i = start, j = end;   
            do {   
                while ((numbers[i] < base) && (i < end))   
                    i++;   
                while ((numbers[j] > base) && (j > start))   
                    j--;   
                if (i <= j) {   
                    temp = numbers[i];   
                    numbers[i] = numbers[j];   
                    numbers[j] = temp;   
                    i++;   
                    j--;   
                }   
            } while (i <= j);   
            if (start < j)   
                quickSort(numbers, start, j);   
            if (end > i)   
                quickSort(numbers, i, end);   
        }   
    } 
  3. 归并排序

    /**  
     * 归并排序   
     *   
     *  申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 
     *  设定两个指针,最初位置分别为两个已经排序序列的起始位置   
     *  比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 
     *  重复步骤3直到某一指针达到序列尾   
     *  将另一序列剩下的所有元素直接复制到合并序列尾  
     *   
     * @param numbers  
     */  
    public static void mergeSort(int[] numbers, int left, int right) {   
        int t = 1;// 每组元素个数   
        int size = right - left + 1;   
        while (t < size) {   
            int s = t;// 本次循环每组元素个数   
            t = 2 * s;   
            int i = left;   
            while (i + (t - 1) < size) {   
                merge(numbers, i, i + (s - 1), i + (t - 1));   
                i += t;   
            }   
            if (i + (s - 1) < right)   
                merge(numbers, i, i + (s - 1), right);   
        }   
    }  
  4. 插入排序

        /**  
     * 插入排序   
     *   
     *  从第一个元素开始,该元素可以认为已经被排序 
     *  取出下一个元素,在已经排序的元素序列中从后向前扫描  
     *  如果该元素(已排序)大于新元素,将该元素移到下一位置   
     *  重复步骤3,直到找到已排序的元素小于或者等于新元素的位置   
     *  将新元素插入到该位置中   
     *  重复步骤2    
     * @param numbers  
     */  
    public static void insertSort(int[] numbers) {   
        int size = numbers.length, temp, j;   
        for(int i=1; i<size; i++) {   
            temp = numbers[i];   
            for(j = i; j > 0 && temp < numbers[j-1]; j--)   
                numbers[j] = numbers[j-1];   
            numbers[j] = temp;   
        }   
    }  
  5. 选择排序

    /**  
     * 选择排序
     * 在未排序序列中找到最小元素,存放到排序序列的起始位置  
     * 再从剩余未排序元素中继续寻找最小元素,然后放到排序序列起始位置。  
     * 以此类推,直到所有元素均排序完毕。  
     *   
     * @param numbers  
     */  
    public static void selectSort(int[] numbers) {   
        int size = numbers.length;
       int temp;   
        for (int i = 0; i < size; i++) {   
            int k = i;   
            for (int j = size - 1; j >i; j--)  {   
                if (numbers[j] < numbers[k]) {
             k = j;   
           }
            }   
            temp = numbers[i];   
            numbers[i] = numbers[k];   
            numbers[k] = temp;   
        }   
    } 
  6. 希尔排序

        
        123123

二叉树

  • 遍历二叉树

    // 创建一棵树
    public class Node {  
        private int data;  
        private Node leftNode;  
        private Node rightNode;  
        public Node(int data, Node leftNode, Node rightNode){  
            this.data = data;  
            this.leftNode = leftNode;  
            this.rightNode = rightNode;  
        }  
      
        public int getData() {  
            return data;  
        }  
        public void setData(int data) {  
            this.data = data;  
        }  
        public Node getLeftNode() {  
            return leftNode;  
        }  
        public void setLeftNode(Node leftNode) {  
            this.leftNode = leftNode;  
        }  
        public Node getRightNode() {  
            return rightNode;  
        }  
        public void setRightNode(Node rightNode) {  
            this.rightNode = rightNode;  
        }  
    }  
    // 递归
    public class BinaryTree {  
        /** 
         * @author yaobo
         * 二叉树的先序中序后序排序 
         */  
        public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错  
            Node J = new Node(8, null, null);  
            Node H = new Node(4, null, null);  
            Node G = new Node(2, null, null);  
            Node F = new Node(7, null, J);  
            Node E = new Node(5, H, null);  
            Node D = new Node(1, null, G);  
            Node C = new Node(9, F, null);  
            Node B = new Node(3, D, E);  
            Node A = new Node(6, B, C);  
            return A;   //返回根节点  
        }
        
        public void printNode(Node node){  
            System.out.print(node.getData());  
        }  
        public void theFirstTraversal(Node root) {  //先序遍历  
            printNode(root);  
            if (root.getLeftNode() != null) {  //使用递归进行遍历左孩子  
                theFirstTraversal(root.getLeftNode());  
            }  
            if (root.getRightNode() != null) {  //递归遍历右孩子  
                theFirstTraversal(root.getRightNode());  
            }  
        }  
        public void theInOrderTraversal(Node root) {  //中序遍历  
            if (root.getLeftNode() != null) {  
                theInOrderTraversal(root.getLeftNode());  
            }  
            printNode(root);  
            if (root.getRightNode() != null) {  
                theInOrderTraversal(root.getRightNode());  
            }  
        }
        
        
        public void thePostOrderTraversal(Node root) {  //后序遍历  
            if (root.getLeftNode() != null) {  
                thePostOrderTraversal(root.getLeftNode());  
            }  
            if(root.getRightNode() != null) {  
                thePostOrderTraversal(root.getRightNode());  
            }  
            printNode(root);  
        }  
          
        public static void main(String[] args) {  
            BinaryTree tree = new BinaryTree();  
            Node root = tree.init();  
            System.out.println("先序遍历");  
            tree.theFirstTraversal(root);  
            System.out.println("");  
            System.out.println("中序遍历");  
            tree.theInOrderTraversal(root);  
            System.out.println("");  
            System.out.println("后序遍历");  
            tree.thePostOrderTraversal(root);  
            System.out.println("");  
        }  
    }  
    // 堆栈
    public class BinaryTree1 { 
         public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错  
                Node J = new Node(8, null, null);  
                Node H = new Node(4, null, null);  
                Node G = new Node(2, null, null);  
                Node F = new Node(7, null, J);  
                Node E = new Node(5, H, null);  
                Node D = new Node(1, null, G);  
                Node C = new Node(9, F, null);  
                Node B = new Node(3, D, E);  
                Node A = new Node(6, B, C);  
                return A;   //返回根节点  
            } 
        
        public void printNode(Node node){  
            System.out.print(node.getData());  
        }
        
        
        public void theFirstTraversal_Stack(Node root) {  //先序遍历  
            Stack<Node> stack = new Stack<Node>();  
            Node node = root;  
            while (node != null || stack.size() > 0) {  //将所有左孩子压栈  
                if (node != null) {   //压栈之前先访问  
                    printNode(node);  
                    stack.push(node);  
                    node = node.getLeftNode();  
                } else {  
                    node = stack.pop();  
                    node = node.getRightNode();  
                }  
            }  
        }  
          
        public void theInOrderTraversal_Stack(Node root) {  //中序遍历  
            Stack<Node> stack = new Stack<Node>();  
            Node node = root;  
            while (node != null || stack.size() > 0) {  
                if (node != null) {  
                    stack.push(node);   //直接压栈  
                    node = node.getLeftNode();  
                } else {  
                    node = stack.pop(); //出栈并访问  
                    printNode(node);  
                    node = node.getRightNode(); 
                }  
            }  
        }  
          
        public void thePostOrderTraversal_Stack(Node root) {   //后序遍历  
            Stack<Node> stack = new Stack<Node>();  
            Stack<Node> output = new Stack<Node>();//构造一个中间栈来存储逆后序遍历的结果  
            Node node = root;  
            while (node != null || stack.size() > 0) {  
                if (node != null) {  
                    output.push(node);  
                    stack.push(node);                 
                    node = node.getRightNode();  
                } else {  
                    node = stack.pop();               
                    node = node.getLeftNode();
                }  
            }  
            System.out.println(output.size());
            while (output.size() > 0) {
                
                printNode(output.pop());  
            }  
        }
        
        public static void main(String[] args) {  
            BinaryTree1 tree = new BinaryTree1();  
            Node root = tree.init();  
            System.out.println("先序遍历");  
            tree.theFirstTraversal_Stack(root);  
            System.out.println("");  
            System.out.println("中序遍历");  
            tree.theInOrderTraversal_Stack(root);  
            System.out.println("");  
            System.out.println("后序遍历");  
            tree.thePostOrderTraversal_Stack(root);  
            System.out.println("");  
        }
    }