程序员必须掌握的几种排序算法

常用的几种排序分类

        1、插入排序(直接插入排序、希尔排序) 
        2、交换排序(冒泡排序、快速排序) 
        3、选择排序(直接选择排序、堆排序) 
        4、归并排序 
        5、分配排序(基数排序)


1、冒泡排序

              冒泡排序(Bubble Sort),是一种较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
              这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
演示:

@Test  Java方法
public void bubbleSort() {
	int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
	// 统计比较次数
	int count = 0;
	for (int i = 0; i < arr.length - 1; i++) {
		boolean flag = true;
		for (int j = 0; j < arr.length - 1 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				// 交换位置
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = false;
			}
			count++;
		}
		if(flag) {
			break;
		}
	}
	System.out.println(Arrays.toString(arr));
	System.out.println("一共比较了:" + count + "次");
}


运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
一共比较了:95次
JavaScript方法        

function bubbleSort(){
    var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
    // 统计比较次数
    var count = 0;
   for (int i = 0; i < arr.length - 1; i++) {
		var flag = true;
		for (int j = 0; j < arr.length - 1 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				// 交换位置
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = false;
			}
			count++;
		}
		if(flag) {
			break;
		}
	}
    return arr,count;
}

运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
一共比较了:95次

2.选择排序

             选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
演示:

@Test    Java方法
public void SelectionSort() {
	int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
	for (int i = 0; i < arr.length - 1; i++) {
		int index = i;
		for (int j = 1 + i; j < arr.length; j++) {
			if (arr[j] < arr[index]) {
				index = j;// 保存最小元素的下标
			}
		}
		// 此时已经找到最小元素的下标
		// 将最小元素与前面的元素交换
		int temp = arr[index];
		arr[index] = arr[i];
		arr[i] = temp;
	}
	System.out.println(Arrays.toString(arr));
}

运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

@text    JavaScript方法
function SelectionSort(){
    var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 ];
    for (int i = 0; i < arr.length - 1; i++) {
		int index = i;
		for (int j = 1 + i; j < arr.length; j++) {
			if (arr[j] < arr[index]) {
				index = j;// 保存最小元素的下标
			}
		}
		// 此时已经找到最小元素的下标
		// 将最小元素与前面的元素交换
		int temp = arr[index];
		arr[index] = arr[i];
		arr[i] = temp;
	}
    return arr;
}

运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

3.插入排序

           插入排序(Insertion sort)是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
            插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入到前面已经排序的数组中的适当位置上,直到全部插入完为止。
演示:

@Test    Java方法
public void InsertionSort() {
	int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
	for (int i = 1; i < arr.length; i++) {
		// 定义待插入的数
		int insertValue = arr[i];
		// 找到待插入数的前一个数的下标
		int insertIndex = i - 1;
		while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
			arr[insertIndex + 1] = arr[insertIndex];
			insertIndex--;
		}
		arr[insertIndex + 1] = insertValue;
	}
	System.out.println(Arrays.toString(arr));
}
@Test    JavaScript方法
function InsertionSort() {
	var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 ];
	for (int i = 1; i < arr.length; i++) {
		// 定义待插入的数
		var insertValue = arr[i];
		// 找到待插入数的前一个数的下标
		var insertIndex = i - 1;
		while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
			arr[insertIndex + 1] = arr[insertIndex];
			insertIndex--;
		}
		arr[insertIndex + 1] = insertValue;
	}
	return arr;
}

4.希尔排序

            传统的插入排序算法在某些场景中存在着一些问题,例如[2,3,4,5,1]这样的一个数组,当我们对其进行插入排序的时候,发现要插入的数字是1,而要想将1插入到最前面,需要经过四个步骤,分别将5、4、3、2后移。所以得出结论:如果较小的数是我们需要进行插入的数,那效率就会比较低。鉴于这种场景的缺陷,希尔排序诞生了,它是插入排序的一种更高效的版本。
先看看希尔排序的概念:
           希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

演示:

动画如果没有看懂,我这里再贴几张静态图:

@Test    Java方法
public void ShellSort() {
	int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
	for (int gap = arr.length / 2; gap > 0; gap /= 2) {
		// 对数组元素进行分组
		for (int i = gap; i < arr.length; i++) {
			// 遍历各组中的元素
			for (int j = i - gap; j >= 0; j -= gap) {
				// 交换元素
				if (arr[j] > arr[j + gap]) {
					int temp = arr[j];
					arr[j] = arr[j + gap];
					arr[j + gap] = temp;
				}
			}
		}
	}

	System.out.println(Arrays.toString(arr));
}


运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
@Test    JavaScript运行
public void ShellSort() {
	var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 ];
	for (var gap = arr.length / 2; gap > 0; gap /= 2) {
		// 对数组元素进行分组
		for (var i = gap; i < arr.length; i++) {
			// 遍历各组中的元素
			for (var j = i - gap; j >= 0; j -= gap) {
				// 交换元素
				if (arr[j] > arr[j + gap]) {
					var temp = arr[j];
					arr[j] = arr[j + gap];
					arr[j + gap] = temp;
				}
			}
		}
	}
    
    return arr;
}



运行结果:
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

                    那么在上面的程序段中,数组长度为15,所以在第一轮,数组被分为了15 / 2 = 7个小组,然后分别对每个小组的元素进行遍历。在第一轮中小组之间的元素间隔都为7,所以分成的小组数其实也就是元素之间的间隔。接着就可以对每个小组的元素进行比较,然后进行交换,接下来以此类推。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值