查找算法,排序算法,遍历算法之Java实现

文章目录

    • 1.查找算法
        • 1.二分/折半查找
    • 2.排序算法
        • 1.冒泡排序(Bubble Sort)-----不推荐
        • 2.选择排序(Selection Sort)----不推荐
        • 3.插入排序(Insertion Sort)----不推荐
        • 4.快速排序(Quick Sort)----推荐
        • 5.堆排序(Heap Sort)----推荐
    • 3.遍历算法
        • 节点结构
        • 1.先序遍历
        • 2.中序遍历(非递归)
        • 3.层次遍历

1.查找算法

1.二分/折半查找

  • 时间复杂度:O(logn)
  • 空间复杂度
public static int binarySearch(int[] array, int value) {
     
    int low = 0;
    int high = array.length - 1;
    while (low <= high) {
     
        int middle = (low + high) >> 1;
        if (value == array[middle]) {
     
            return middle;
        }
        if (value > array[middle]) {
     
            low = middle + 1;
        }
        if (value < array[middle]) {
     
            high = middle - 1;
        }
    }
    return -1;
}

2.排序算法

1.冒泡排序(Bubble Sort)-----不推荐

原理:从前往后或者从后往前一个一个比较,每次会确定一个未排序中的最大值(最小值)的最终位置

算法分析

  • 平均复杂度 O(n2)
  • 最差复杂度 O(n2)

   public int[] bubbleSort(int[] n) {
     
        //趟数
        for (int i = 0; i < n.length - 1; i++) {
     
            //0~i已经有序,从后往前排,后面小的则和前面的交换
            for (int j = n.length - 1; j > i; j--) {
     
                if (n[j] < n[j - 1]) {
     
                    int temp = n[j - 1];
                    n[j - 1] = n[j];
                    n[j] = temp;
                }
            }
        }
        return n;
    }

2.选择排序(Selection Sort)----不推荐

原理:每次会确定一个未排序中的最大值(最小值)的最终位置,若从低到高排序,每次选择未排序中最小的和第一个元素交换,直至遍历完列表,再进行下一次选择。

算法分析

  • 平均复杂度 O(n2)
  • 最差复杂度 O(n2)

    public static int[] selectionSort(int[] array) {
     
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++) {
     
            int minIndex = i;
            for (int j = i; j < array.length; j++) {
     
                if (array[j] < array[minIndex]) //找到最小的数
                    minIndex = j; //将最小数的索引保存
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
        return array;
    }

3.插入排序(Insertion Sort)----不推荐

原理:每次会确定一个未排序中的最大值(最小值)的最终位置,若从低到高排序,每次选择未排序中最小的和第一个元素交换,直至遍历完列表,再进行下一次选择。

算法分析

  • 平均复杂度 O(n2)
  • 最差复杂度 O(n2)
   /**
     * 插入排序
     * @param array
     * @return
     */
    public static int[] insertionSort(int[] array) {
     
        if (array.length == 0)
            return array;
        int current;
        for (int i = 0; i < array.length - 1; i++) {
     
            current = array[i + 1];
            int preIndex = i;
            while (preIndex >= 0 && current < array[preIndex]) {
     
                array[preIndex + 1] = array[preIndex];
                preIndex--;
            }
            array[preIndex + 1] = current;
        }
        return array;
    }

4.快速排序(Quick Sort)----推荐

原理:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

算法分析

  • 平均复杂度 O(nlogn)
  • 最差复杂度 O(n2)

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 步骤1:从数列中挑出一个元素,称为 “基准”(pivot );
  • 步骤2:重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 步骤3:递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
    static void quicksort(int n[], int left, int right) {
     
        int dp;
        if (left < right) {
     
            dp = partition(n, left, right);
            quicksort(n, left, dp - 1);
            quicksort(n, dp + 1, right);
        }
    }
 
    static int partition(int n[], int left, int right) {
     
        int pivot = n[left];
        while (left < right) {
     
            while (left < right && n[right] >= pivot)
                right--; 
                n[left++] = n[right];
            while (left < right && n[left] <= pivot)
                left++;
                n[right--] = n[left];
        }
        n[left] = pivot;
        return left;
    }

5.堆排序(Heap Sort)----推荐

堆排序(Heapsort) 是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

算法分析

  • 平均复杂度 O(nlogn)
  • 最差复杂度 O(nlogn)

堆排序适用于找出超大量数据的前几名,相比于快速排序,堆排序只需要维护一个很小的树即可完成前几名的排序,而快排可能会有内存溢出的风险。

7.1 算法描述

  • 步骤1:将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 步骤2:将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
  • 步骤3:由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
//声明全局变量,用于记录数组array的长度;
    static int len;
    /**
     * 堆排序算法
     *
     * @param array
     * @return
     */
    public static int[] HeapSort(int[] array) {
     
        len = array.length;
        if (len < 1) return array;
        //1.构建一个最大堆
        buildMaxHeap(array);
        //2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
        while (len > 0) {
     
            swap(array, 0, len - 1);
            len--;
            adjustHeap(array, 0);
        }
        return array;
    }
    /**
     * 建立最大堆
     *
     * @param array
     */
    public static void buildMaxHeap(int[] array) {
     
        //从最后一个非叶子节点开始向上构造最大堆
        //for循环这样写会更好一点:i的左子树和右子树分别2i+1和2(i+1)
        for (int i = (len/2- 1); i >= 0; i--) {
     
            adjustHeap(array, i);
        }
    }
    /**
     * 调整使之成为最大堆
     *
     * @param array
     * @param i
     */
    public static void adjustHeap(int[] array, int i) {
     
        int maxIndex = i;
        //如果有左子树,且左子树大于父节点,则将最大指针指向左子树
        if (i * 2 < len && array[i * 2] > array[maxIndex])
            maxIndex = i * 2 + 1;
        //如果有右子树,且右子树大于父节点,则将最大指针指向右子树
        if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex])
            maxIndex = i * 2 + 2; 
        //如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
        if (maxIndex != i) {
     
            swap(array, maxIndex, i);
            adjustHeap(array, maxIndex);
        }
    }

3.遍历算法

节点结构

class TreeNode{
     //节点结构
    int value;
    TreeNode left;
    TreeNode right;

    TreeNode(int value) {
     
        this.value = value;
    }
}

1.先序遍历

  • 递归
void preOrder(TreeNode node) {
     
        if (node != null) {
     
            System.out.println(node);
            preOrder(node.left);
            preOrder(node.right);
        }
    }
  • 非递归(队列实现)
void preOrder2(TreeNode node) {
     
        LinkedList queue = new LinkedList();
        TreeNode p = node;
        while (p != null || queue.isEmpty()) {
     
            if (p != null) {
     
                queue.add(p);
                p = p.left;
            } else {
     
                p = (TreeNode) queue.poll();
                System.out.println(p);
                p = p.right;
            }
        }
    }

2.中序遍历(非递归)

void inOrder(TreeNode node) {
     
        Stack stack = new Stack();
        TreeNode p = node;
        while (p != null || stack.isEmpty()) {
     
            if (p != null) {
     
                stack.push(p);
                p = p.left;
            } else {
     
                p = (TreeNode) stack.pop();
                System.out.println(p);
                p = p.right;
            }
        }
    }

3.层次遍历

void levelOrder(TreeNode node) {
     
        LinkedList queue = new LinkedList();
        TreeNode p;
        queue.add(node);
        while (!queue.isEmpty()) {
     
            p = (TreeNode) queue.poll();
            System.out.println(p);
            if (p.left != null) {
     
                queue.add(p.left);
            }
            if (p.right != null) {
     
                queue.add(p.right);
            }
        }
    }

你可能感兴趣的:(Java数据结构精析,排序算法,java,数据结构,算法)