数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排

第十一章 

最常用的:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第1张图片

 

1.冒泡排序

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第2张图片

当某次冒泡操作已经没有数据交换时,说明已经达到完全有序,不用再继续执行后续的冒泡操作

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第3张图片

代码

/**
 * @author: xuxu
 * @date 2020/2/27 9:29
 * @Description: 冒泡排序
 */
public class BubbleSort {

    public static void bubbleSort(int[] arr){
        //控制第几次排序
        for(int i=0;iarr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j]=temp;
                    isSort=true;
                }
            }
            if(!isSort){
                System.out.print("第"+(i+1)+"次排序后数组无变化退出");
                break;
            }
            //遍历
            System.out.print("第"+(i+1)+"次排序后数组为:");
            for (int k=0;k

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第4张图片

 

2.插入排序

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第5张图片

首先,我们将数组中的数据分为两个区间,已排序区间未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。

插入排序也包含两种操作,一种是元素的比较,一种是元素移动。当我们需要将一个数据 a 插入到已排序区间时,需要拿 a 与已排序区间的元素依次比较大小,找到合适的插入位置。找到插入点之后,我们还需要将插入点之后的元素顺序往后移动一位,这样才能腾出位置给元素 a 插入。

/**
 * @author: xuxu
 * @date 2020/2/27 9:56
 * @Description:插入排序
 */
public class InsertSort {

    public static void  insertSort(int[] arr){
        //这里循环的是未排序部分
        for(int i=1;i=0;j--){
                //如果前一个数字大于要插入的数字则向后移动让出位置
                if(arr[j]>insertNum){
                    arr[j+1] = arr[j];
                }else{
                    //一旦他找到对的位置,则不需要向前继续找,因为前面是排好序的
                    break;
                }
            }
            //将要插入的数放入前面找到的插入的位置 这里j+1是因为前面j--了
            arr[j+1]=insertNum;
            //遍历
            System.out.print("第"+(i)+"次排序后数组为:");
            for (int k=0;k

 

3.选择排序

选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第6张图片

/**
 * @author: xuxu
 * @date 2020/2/27 11:02
 * @Description: 选择排序
 */
public class SelectSort {

    public static void selectSort(int[] arr){
        for (int i=0;iarr[min+1]){
                    //先找出未排序区最小的一个下标
                    min = min+1;
                }
            }
            //将min放入已排序区的最后面,同时原位置的元素放在min处
            int temp = arr[i];
            arr[i]=arr[min];
            arr[min] = temp;

            //遍历
            System.out.print("第"+(i+1)+"次排序后数组为:");
            for (int k=0;k

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第7张图片

从推荐使用的角度看 插入>冒泡>选择

 

冒泡排序、插入排序、选择排序这三种排序算法,它们的时间复杂度都是 O(n2),比较高,适合小规模数据的排序。

归并排序快速排序两种时间复杂度为 O(nlogn) 。这两种排序算法适合大规模的数据排序

归并排序和快速排序都用到了分治思想

 

4.归并排序

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第8张图片

分治算法一般都是用递归来实现的。分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突。

递归公式

递推公式:
merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
 
终止条件:
p >= r 不用再继续分解

merge_sort(p…r) 表示,给下标从 p 到 r 之间的数组排序。我们将这个排序问题转化为了两个子问题,merge_sort(p…q) 和 merge_sort(q+1…r),其中下标 q 等于 p 和 r 的中间位置,也就是 (p+r)/2。当下标从 p 到 q 和从 q+1 到 r 这两个子数组都排好序之后,我们再将两个有序的子数组合并在一起,这样下标从 p 到 r 之间的数据就也排好序了

合并过程

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第9张图片

我们申请一个临时数组 tmp,大小与 A[p…r] 相同。我们用两个游标 i 和 j,分别指向 A[p…q] 和 A[q+1…r] 的第一个元素。比较这两个元素 A[i] 和 A[j],如果 A[i]<=A[j],我们就把 A[i] 放入到临时数组 tmp,并且 i 后移一位,否则将 A[j] 放入到数组 tmp,j 后移一位。

继续上述比较过程,直到其中一个子数组中的所有数据都放入临时数组中,再把另一个数组中的数据依次加入到临时数组的末尾,这个时候,临时数组中存储的就是两个子数组合并之后的结果了。最后再把临时数组 tmp 中的数据拷贝到原数组 A[p…r] 中。

/**
 * @author: xuxu
 * @date 2020/2/27 14:32
 * @Description: 归并排序
 * f(a,p) =f(a,q)+f(q+1,p)
 */
public class MergeSort {

    public static void mergeSort(int[] arr,int begin,int end ){
        if(begin>=end){
            return ;
        }
        //中间位置
        int mid = (begin+end)/2;
        //递归分解合并
        mergeSort(arr, begin, mid);
        mergeSort(arr, mid+1 ,end);
        merge(arr,begin,mid,end);
    }

    /**
     * 合并操作
     */
    public static void merge(int[] arr, int begin, int mid, int end){
        int[] mergeArr=new int[arr.length];
        //数组1的指针
        int p1 = begin;
        //数组2的指针
        int p2 = mid+1;
        //合并的数组起始位置
        int index=begin;
        while(p1<=mid && p2<=end){
            if(arr[p1]>=arr[p2]){
                mergeArr[index++]=arr[p2++];
            }else{
                mergeArr[index++]=arr[p1++];
            }
        }
        while(p1<=mid){
            mergeArr[index++] = arr[p1++];
        }
        while(p2<=end){
            mergeArr[index++] = arr[p2++];
        }

        for(int i=begin;i<=end;i++){
            arr[i] = mergeArr[i];
        }
    }

    public static void main(String[] args) {
        int[] arr = {6,5,3,4,2,1,7};
        mergeSort(arr, 0, arr.length-1);
        System.out.print("排序后数组元素为:");
        for (int i=0;i

 

5.快速排序

基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分

实现

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第10张图片

数据结构与算法之美学习笔记(11章) 排序,冒泡,插入,选择,归并,快排_第11张图片

public class QuickSort {
	
	public static int getMid(int[] nums,int low,int high){
		int temp=nums[low];
		while(low=temp){
				high--;
			}
			nums[low]=nums[high];//如果右边小于中间数 移动到左边
			while(low

 

 

 

 

 

 

 

 

你可能感兴趣的:(#,数据结构(排序,查询))