【笔记】算法

  1. 算法复杂度速查表
  2. 十大经典排序算法
  3. 程序员必须掌握的核心算法有哪些?

排序算法

冒泡排序、选择排序、插入排序共有特性

  • 均为简单排序
  • n个数,比较n-1轮
  • 第i轮比较时,需比较n-i次
  • 时间复杂度均为O(n^2)

冒泡排序

/**
 * 冒泡排序
 * 
 * 每一轮,前一个数和后一个数比,若是前数大,则交换位置,第一轮找出最大值放在末尾,下一轮不参与比较
 * 以此类推
 */
public class Bubble {
    public static void bubbleSort(int[] a){
    	
        for(int i=1;i<a.length;i++){
        
	        // 优化,增加flag,若当前轮数未出现交换,则证明此时数组已经排序结束
	    	boolean flag= true;
	    	
            for(int j=0;j<a.length-i;j++){
                if(a[j]>a[j+1]){
                    Test.swap(a,j,j+1);
                    flag= false;
                }
            }
            if(flag){
            	break;
            }
        }
    }
}

选择排序

/**
 * 选择排序
 * 
 * 第一轮,找到所有数中的最小值,放在第一个位置
 * 第二轮,找到除去第一个之外的最小值,放在第二个位置
 * 以此类推
 */
public class Select {

    public static void selectSort(int[] a) {
    	// i=0, 第一轮比较,备份第一个数,下标为i,假设当前数为最小值
        for (int i = 0; i < a.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[min] > a[j]) {
                    min = j;
                }
            }
            if (min != i) {
                Test.swap(a, i, min);
            }
        }
    }

}

插入排序

/**
 * 插入排序(打扑克原理)
 * 
 * 左边数据当做有序,右侧当做无序
 * 第一轮,与左侧数据比较,当小于左侧数据时,交换位置
 * 以此类推
 */
public class Insert {

    public static void insertSort(int[] a) {
        for (int i = 1; i < a.length ; i++) {
            int temp=i;
            for (int j = i-1; j >= 0; j--) {
                if (a[temp] < a[j]) {
                    Test.swap(a, j, temp);
                    temp = j;
                }
            }
        }
    }

}

堆排序

/**
 * 堆排序
 * 
 * 构建大顶堆
 * 将堆顶(即最大值)与末尾元素交换,则数组最大值已确定
 * 除去末尾值重新构建大顶堆
 * 以此类推
 */
public class Heap {

    public static void heapSort(int[] a) {
        int len = a.length;
        // 所有非叶子节点进行大顶堆的构建,从下至上
        for (int i = (len - 2) / 2; i >= 0; i--) {
            adjustHeap(a, i, len);
        }
        for (int i = len - 1; i > 0; i--) {
            Test.swap(a, i, 0);
            adjustHeap(a, 0, i);
        }
    }

    /**
     * 构建大顶堆
     * @param a
     */
    private static void adjustHeap(int[] a, int i, int len) {
        // 备份当前节点
        int temp = a[i];
        // 从左至右,找到当前节点的左孩子
        for (int j = i * 2 + 1; j < len; j = j * 2 + 1) {
            // 左孩子与右孩子比较,找到最大值
            if (j + 1 < len && a[j] < a[j + 1]) {
                j++;
            }
            // 父节点值更大
            if (temp >= a[j]) {
                break;
            }
            // 子节点值更大,与子节点交换
            else {
                a[i] = a[j];
                i = j;
            }
        }
        a[i] = temp;
    }
}

快速排序

public class Quick {

    public static void quickSort(int[] a, int left, int right) {
        if (left < right) {
       		 // 使用分治法策略来把一个串行(list)分为两个子串行(sub-lists)
            int meetting = partition(a, left, right);
            quickSort(a, 0, meetting - 1);
            quickSort(a, meetting + 1, right);
        }
    }

    /**
     * i<j
     * j从右侧开始,找到比基准值小的数时,停止
     * i从左侧开始,找到比基准值大的数停止,交换i与j的值
     * 继续寻找,直至相遇,相遇位置与基准值进行交换
     */
    private static int partition(int[] a, int left, int right) {
    	// 优化,通常取第一个数为基准值,若该数过大或过小,增加算法复杂度,取首尾中间三数的中间值作为基准,更为合适
        setBase(a,left,right);
        
        int temp = a[left];
        while (left < right) {
            while (left < right && a[right] >= temp) {
                right--;
            }
            a[left] = a[right];
            while (left < right && a[left] <= temp) {
                left++;
            }
            a[right] = a[left];
        }
        a[left] = temp;
        return left;
    }

	// 三数取中,设置基准值,在第一个位置
    public static void setBase(int[] a, int left, int right) {
        int mid = (left + right) / 2;
        if (a[mid] > a[right]) {
            Test.swap(a, mid, right);
        }
        if (a[left] > a[right]) {
            Test.swap(a, left, right);
        }
        if (a[mid] > a[left]) {
            Test.swap(a, left, mid);
        }
    }

}

测试及总结

设定某一基准值,小于该值则选择插入排序(插入排序是简单排序中性能最好的),大于该值,选择快速排序(复杂排序中速度最快)

public class Test {

    public static void main(String[] args) {
        int[] a = new int[5];
        for (int i = 0; i < a.length; i++) {
            a[i] = (int) (Math.random() * a.length * 10);
        }
        System.out.println(Arrays.toString(a));

//        Bubble.bubbleSort(a);
//        Insert.insertSort(a);
//        Select.selectSort(a);

//        Heap.heapSort(a);
//        Quick.quickSort(a, 0, a.length - 1);

        sort(a);
        System.out.println(Arrays.toString(a));

    }

    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    public static void sort(int[] a) {
        int pivot = 50;
        if (a.length < pivot) {
            Insert.insertSort(a);
        } else {
            Quick.quickSort(a, 0, a.length - 1);
        }
    }

}

算法时间复杂度速查表

转自每个程序员都应该收藏的算法复杂度速查表

抽象数据结构的操作复杂度

在这里插入图片描述

数组排序

在这里插入图片描述

图操作

堆操作

在这里插入图片描述

大-O 复杂度曲线

在这里插入图片描述

发布了37 篇原创文章 · 获赞 0 · 访问量 1133

猜你喜欢

转载自blog.csdn.net/qq_25046005/article/details/104419445