常见排序算法流程分析及其实现代码

排序算法时间复杂度空间复杂度稳定性
直接插入排序O(n2)O(1)稳定
折半插入排序O(n2)O(1)稳定
希尔排序O(n1.3)O(1)不稳定
冒泡排序O(n2)O(1)稳定
快速排序O(nlog2n)O(log2n)不稳定
简单选择排序O(n2)O(1)不稳定
堆排序O(nlog2n)O(1)不稳定
二路归并排序O(nlog2n)O(n)稳定
基数排序O(d(n+rd))O(rd)稳定

一、直接插入排序

1、执行流程

每趟将一个待排序的元素依次与已经比较完并排好序的序列比较并插入到相应的位置,直到所有待排序元素都被插入到有序序列中为止

原始序列:49 38 65 97 76 13 27 49
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

1)首先看49,直接放入有序序列中

  49   38 65 97 76 13 27 49

2)插入38,38<49,所以38插入49之前

  38 49   65 97 76 13 27 49

3)插入65,65>49,所以不需要移动有序序列

  38 49 65   97 76 13 27 49

4)插入97,97>65,所以不需要移动有序序列

  38 49 65 97  76 13 27 49

5)插入76,76<97,所以97向后移动一位,76继续与65比较,76>65,所以76应该插入在65之后,97之前

  38 49 65 76 97  13 27 49

6)插入13,同理可得

  13 38 49 65 76 97  27 49

7)插入27,同理可得

  13 27 38 49 65 76 97  49

8)插入49,同理可得

  13 27 38 49 49 65 76 97

得出最终结果

2、实现代码
public class InsertSort {

	public static void sort(int num[], int n) {
		int i, j, k, temp;
		for(i = 1; i < n; i++) {
			temp = num[i];
			j = i - 1;
			while(j >= 0 && temp < num[j]) {
				num[j+1] = num[j];
				j--;
			}
			num[j+1] = temp;
			
			System.out.print("第"+i+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			System.out.println();
			
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49};
		sort(mynum, mynum.length);
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:稳定

二、折半插入排序

1、执行流程

在这个排序算法中,我们会设置四个辅助变量:low,high,mid,temp。

low用来标志待插入有序序列中最小的元素的下标
high用来标志待插入有序序列中最大的元素的下标
mid即为low与high之间最中间的元素的下标,计算方法为(low+high)/2向下取整。
temp用来标志待排元素的下标

每趟排序low初始定义为0,high定义为已排好序序列的最大元素的下标,temp定义为high+1,比较下标为mid和下标为temp所在元素的大小

当temp<mid时,high=mid-1,low不变,重新计算mid,继续比较
当temp>mid时,low=mid+1,high不变,重新计算mid,继续比较
当low>high时停止比较,得出待排元素应插入的位置

原始序列:49 38 65 97 76 13 27 49
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

1)首先看49,直接放入有序序列中

  49   38 65 97 76 13 27 49

2)计算38应插入的位置

low=0;high=0;mid=(0+0)/2=0;temp=38
38<49,high=mid-1=-1,此时low>high,停止比较,即38应插入到49之前

  38 49   65 97 76 13 27 49

3)计算65应插入的位置

low=0;high=1;mid=(0+1)/2=0;temp=65
65>38,low=mid+1=1,low<high,继续比较,mid=(1+1)/2=1
65>49,low=mid+1=2,low>high,停止比较,即65应插入到49之后

  38 49 65  97 76 13 27 49

4)计算97应插入的位置

同理可得

  38 49 65 97  76 13 27 49

5)计算76应插入的位置

low=0;high=3;mid=(0+3)/2=1;temp=76
76>49,low=mid+1=2,mid=(2+3)/2=2
76>65,low=mid+1=3,mid=(3+3)/2=3
76<97,high=mid-1=2,此时low>high,停止比较,即76应插入到97之前

  38 49 65 76 97  13 27 49

剩余比较步骤省略

2、执行代码
public class BinarySort {

	public static void sort(int num[], int n) {
		int i, j, k, low, mid, high, temp;
		for(i = 1; i < n; i++) {
			low = 0;
			high = i - 1;
			temp = num[i];
			while(low <= high) {
				mid = (low + high) / 2;
				if(temp < num[mid]) {
					high = mid - 1;
				}else {
					low = mid + 1;
				}
			}
			for(j = i - 1; j >= high + 1; j--) {
				num[j+1] = num[j];
			}
			num[j+1] = temp;
			System.out.print("第"+i+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49};
		sort(mynum, mynum.length);
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:稳定

三、希尔排序

1、执行流程

原始序列:49 38 65 97 76 13 27 49 55 04
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

因为原始序列长度为10,所以n=10/2=5,按照n=5的增量划分

49   13
  38   27
    65   49
      97   55
        76   04

每组进行直接插入排序,得到

13   49
  27   38
    49   65
      55   97
        04   76

从而得到序列

13 27 49 55 04 49 38 65 97 76

再次计算n/2,即5/2=3,按照n=3的增量划分

13 55 38 76
  27 04 65
    49 49 97

每组进行直接插入排序,得到

13 38 55 76
  04 27 65
    49 49 97

从而得到序列

13 04 49 38 27 49 55 65 97 76

最后以增量为一进行划分,就相当于最后进行一次直接插入排序,得到最终结果

04 13 27 38 49 49 55 65 76 97

2、执行代码
public class ShellSort {

	public static void sort(int num[], int n) {
		int i, j, k, temp;
		int count = 0;
		while(n > 1) {
			n = n / 2;
			for(i = 0; i < n; i++) {
				for(j = i + n; j < num.length; j = j + n) {
					temp = num[j];
					for(k = j - n; k >= 0 && num[k] > temp; k = k - n) {
						num[k + n] = num[k];
					}
					num[k + n] = temp;
				}
			}
			System.out.print("第"+(++count)+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49, 55, 4};
		sort(mynum, mynum.length);
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(n1.3) — O(n2)
空间复杂度:O(1)
稳定性:不稳定

四、冒泡排序

1、执行流程

首先第一个元素和第二个元素比较,如果第一个元素较大,则交换两者位置,否则不交换;继续比较第二个元素和第三个元素,第三个与第四个元素,直到最大的元素被放在了最后面,一趟冒泡排序完成。经过多趟冒泡排序后,最终的序列即为有序序列

原始序列:49 38 65 97 76 13 27 49
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

1)第一趟

49>38,交换
38 49 65 97 76 13 27 49

49<65,不交换
38 49 65 97 76 13 27 49

65<97,不交换
38 49 65 97 76 13 27 49

97>76,交换
38 49 65 76 97 13 27 49

97>13,交换
38 49 65 76 13 97 27 49

97>27,交换
38 49 65 76 13 27 97 49

97>49,交换
38 49 65 76 13 27 49 97

至此一趟冒泡排序完成,最大的数97被放在了最后

2)第二趟

38<49,不交换

49<65,不交换

65<76,不交换

76>13,交换
38 49 65 13 76 27 49 97

76>27,交换
38 49 65 13 27 76 49 97

76>49,交换
38 49 65 13 27 49 76 97

至此完成第二趟排序,最大的数76被放在了最后,继续完成后续排序即可得到最终序列

2、执行代码
public class BubbleSort {

	public static void sort(int num[], int n) {
		int i, j, k, flag, temp;
		for(i = n-1; i >= 1; i--) {
			flag = 0;
			for(j = 1; j <= i; j++) {
				if(num[j-1] > num[j]) {
					temp = num[j];
					num[j] = num[j-1];
					num[j-1] = temp;
					flag = 1;
				}
			}
			if(flag == 0) {
				return;
			}
			System.out.print("第"+(n-i)+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49};
		sort(mynum, mynum.length);	
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:稳定

五、快速排序

1、执行流程

每趟排序选择第一个元素作为枢纽,并分别将 i,j 两个变量指向首尾两个元素

首先从 j 开始向前扫描

当 j 所指向的元素小于枢纽值时,将 j 所指向的值赋给 i 所指向的位置,变换扫描方向,由 i 向后扫描
当 i 所指向的元素 大于枢纽值时,将 i 所指向的值赋给 j 所指向的位置,变换扫描方向,由 j 向前扫描
当 i=j 时,枢纽位置最终确定(枢纽前的所有元素均小于枢纽的值,枢纽后的元素均大于枢纽的值),再继续分别对枢纽前后的序列进行排序即可得出最终结果

原始序列:49 38 65 97 76 13 27 49
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

1)第一趟,将第一个数49作为枢纽,i,j分别指向首尾元素

 49 38 65 97 76 13 27 49
  i          j

j 由后向前扫描,扫描到27时小于枢纽值,27<49,将27放在 i 的位置

 49 38 65 97 76 13 27 49
  i        j

 27 38 65 97 76 13  49
  i        j

变换扫描方向,由 i 向后扫描,扫描到65时大于枢纽值,65>49,将65放在 j 所指向的位置

 27 38 65 97 76 13  49
     i     j

 27 38   97 76 13 65 49
     i     j

变换扫描方向,由 j 向前扫描,扫描到13时小于枢纽值,13<49,将13放在 i 所指向的位置

 27 38   97 76 13 65 49
     i    j

 27 38 13 97 76  65 49
     i    j

变换扫描方向,由 i 向后扫描,扫描到97时大于枢纽值,97>49,将97放在 j 所指向的位置

 27 38 13 97 76   65 49
      i   j

 27 38 13   76 97 65 49
      i   j

变换扫描方向,由 j 向前扫描,当 i=j 时,扫描结束,将49枢纽值放入

 27 38 13   76 97 65 49
      ij

 27 38 13 49 76 97 65 49
      ij

第一趟结束可以看出,ij 所指的49左边均小于49,右边均大于49,再继续对这两个序列进行排序,最终即可得到有序序列

2、执行代码
public class QuickSort {
	
	static int count = 0;
	
	public static void sort(int num[], int low, int high) {
		int temp, k;
		int i = low, j = high;
		if(low < high) {
			temp = num[low];
			while(i < j) {
				while(j > i && num[j] >= temp) {
					j--;
				}
				if(i < j) {
					num[i] = num[j];
					i++;
				}
				while(i < j && num[i] < temp) {
					i++;
				}
				if(i < j) {
					num[j] = num[i];
					j--;
				}
			}
			num[i] = temp;
			count++;
			System.out.print("第"+count+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			
			System.out.println();
			sort(num, low, i-1);
			sort(num, i+1, high);
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49};
		sort(mynum, 0, mynum.length-1);	
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(nlog2n)
空间复杂度:O(log2n)
稳定性:不稳定

六、简单选择排序

1、执行流程

从无序序列中找出最小的元素与其第一个元素交换位置(也可以理解为放入有序序列中)

原始序列:49 38 65 97 76 13 27 49
(序列中有两个49,其中一个加粗加以区分并可以验证该排序算法稳定性)

1)选择出最小的元素13,与无序序列第一一个元素49交换

13  38 65 97 76 49 27 49

2)选择出最小的元素27,与无序序列第一个元素38交换

13 27  65 97 76 49 38 49

3)选择出最小的元素38,与无序序列第一个元素65交换

13 27 38  97 76 49 65 49

以此类推即可得出最终序列

2、执行代码
public class SelectSort {
	
	public static void sort(int num[], int n) {
		int i, j, k, temp;
		for(i = 0; i < n; i++) {
			k = i;
			for(j = i+1; j < n; j++) {
				if(num[k] > num[j]) {
					k = j;
				}
			}
			temp = num[i];
			num[i] = num[k];
			num[k] = temp;
			
			System.out.print("第"+(i+1)+"趟:");
			for(k = 0; k < num.length; k++) {
				System.out.print(num[k] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int mynum[] = {49, 38, 65, 97, 76, 13, 27, 49};
		sort(mynum, mynum.length);	
	}
}

在这里插入图片描述

3、性能分析

时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:不稳定

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值