排序算法总结-下

4.堆排序

  • 思路:堆就是一个完全二叉树(小顶堆),

  • 主要解决两个问题:

    • 如何将n个待排序的数构建成堆

      • 输出堆顶元素之后如何调整剩下的n-1个元素,使之成为新的堆
  • 时间复杂度:O(nlogn)

    图解:

这里写图片描述

这里写图片描述

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
private static class HeapSort {
        public HeapSort(int a[]) {
            buildMaxHeapify(a);
            heapSort(a);
            System.out.println("");
            System.out.println("****4.堆排序之后:****");
            for (int i = 0; i < a.length; i++) {
                System.out.print(a[i] + ",");
            }
        }

        // 构建初始最大堆
        // 假设长度为8 那么
        // 第一个父节点就是a[3] 左结点为:a[7]
        // 第二个父节点为:a[1] 左节点为:a[3] 右结点为:a[4]
        // 第三份父节点为:a[2] 左节点为:a[5] 右结点为:a[6]

        public static void buildMaxHeapify(int a[]) {
            System.out.println("字符串的长度为:" + a.length);
            int startIndex = getParentIndex(a.length - 1);
            for (int i = startIndex; i >= 0; i--) {
                maxHeapify(a, a.length, i);
            }
        }

        /**
         * 
         * @param a
         *            数组
         * @param length
         *            数据长度
         * @param index
         *            当前的父节点
         */
        private static void maxHeapify(int[] a, int length, int index) {
            // 与当前左右结点进行比较
            int left = getChildLeftIndex(index);
            int right = getChildRightIndex(index);

            // 进行左右节点值的对比
            int largest = index;
            if (left < length && a[left] > a[index]) {
                largest = left;
            }
            if (right < length && a[right] > a[largest]) {
                largest = right;
            }
            if (largest != index) {
                int temp = a[index];
                a[index] = a[largest];
                a[largest] = temp;
                // 整理节点
                maxHeapify(a, length, largest);
            }
        }

        // 父节点的位置
        private static int getParentIndex(int i) {
            return i / 2;
        }

        // 左孩子的位置
        private static int getChildLeftIndex(int index) {
            return index * 2 + 1;
        }

        // 右孩子的位置
        private static int getChildRightIndex(int index) {
            return index * 2 + 2;
        }

        /**
         * 这个函数的含义就是: 将排好的最大堆的堆顶和最后一个交换再进行最大堆排序 排序:最大值放在末尾,再次进行排序
         * 
         * @param a
         */
        public static void heapSort(int a[]) {
            for (int i = a.length - 1; i > 0; i--) {
                int temp = a[0];
                a[0] = a[i];
                a[i] = temp;
                maxHeapify(a, i, 0);
            }
        }
    }

5.冒泡排序

  • 思路:就是不断的两两比较

  • 时间复杂度:O(n^2)

    图解

    这里写图片描述

    代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static class BubbleSort {

        //简单的冒泡排序
        public static void bubbleSort_A(int a[]) {
            for (int i = 0; i < a.length; i++) {
                for (int j = 0; j < a.length-i- 1; j++) {
                    if (a[j] > a[j + 1]) {
                        Swap(a, j, j + 1);
                    }
                }
            }
        }
        
        //改进的冒泡,添加了标记
        public static void bubbleSort_B(int a[]){
            int n = a.length-1;
            while(n>0){
                int pos = 0;
                for (int i = 0; i < n; i++) {
                    if(a[i]>a[i+1]){
                        pos = i;
                        Swap(a, i, i+1);
                    }
                }
                n = pos;
            }
        }
    }

6.快速排序

  • 思路:

    • 选择一个基准元素
    • 通过一次快排序将待排序数分为两个部分,一部分比基准数小,一部分比基准数大
    • 然后接着对这两部分进行相同的操作,直到序列有序
  • 时间复杂度:O(nlogn)

  • 空间复杂度: O(nlogn)

    图解:

    这里写图片描述

    快速排序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static class QuickSort{
        public static void quickSort(int a[],int low,int high){
            if(low<high){
                int privotLoc = partition(a,low,high);
                quickSort(a, low, privotLoc-1);
                quickSort(a, privotLoc+1, high);
            }
        }
        
        private static int partition(int[] a, int low, int high) {
            int privotKey = a[low];
            while(low<high){
                while(low<high && a[high]>=privotKey)--high;//从后半部分向前扫描
                a[low] = a[high];
                while(low<high && a[low]<=privotKey)++low; //从前部分扫描
                a[high] = a[low];
            }
            a[high] = privotKey;
            return low;
        }
    }