关于排序算法的一些认知(上)

排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列。这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率。

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等,分类如图:
(详细描述参见大神文章:十大经典算法
图片来源于
其中:
(a)时间复杂度:即从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。
(b)空间复杂度:就是从序列的初始状态经过排序移位变换的过程一直到最终的状态所花费的空间开销。
(c)使用场景:排序算法有很多,不同种类的排序算法适合不同种类的情景,可能有时候需要节省空间对时间要求没那么多,反之,有时候则是希望多考虑一些时间,对空间要求没那么高,总之一般都会必须从某一方面做出抉择。
(d)稳定性:稳定性是不管考虑时间和空间必须要考虑的问题,往往也是非常重要的影响选择的因素。
以上名词来源于百度百科
在此次学习过程中,主要分享冒泡排序、选择排序、插入排序和希尔排序四类简单的排序结构。
(1)冒泡排序
冒泡排序(Bubble Sort)是一种较简单的排序算法。它遍历待排序的元素列,依次比较两个相邻的元素,并按照规则对元素进行顺序交换,若直到没有相邻元素需要交换,序列排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

算法实质:把小的元素往前调,大的元素往后调,即升序排列。

算法步骤:
(a)指针置于第一个元素;
(b)移动指针到下一个元素,比较相邻元素大小;若元素小于步骤(a),则交换元素顺序;
(c)重复步骤(b)至排序完成。

C++代码实现:

int sort_data[] = {2,10,15,3,45,1,22,4,50,49,48,27,6,19,35};
int data_length = 15;

void BubbleSort() {
	for (int i = 1; i < data_length; i++) {
		for (int j = 0; j < data_length-i; j++) {
			if (sort_data[j+1] < sort_data[j]) {
				int temp = sort_data[j];
				sort_data[j] = sort_data[j+1];
				sort_data[j + 1] = temp;
			}
		}
	}
}

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

算法实质:选择未排序元素列中的最小值,插入已排序元素列的末尾。

算法步骤:
(a)遍历元素列,找到最小值,并存放在列的第一位,记为已排列元素列,其余为未排序列;
(b)遍历未排序列,找到最小值,并将其放在已排列序列的第二位;
(c)重复步骤(b)至排序完成。

C++代码实现:

int sort_data[] = {2,10,15,3,45,1,22,4,50,49,48,27,6,19,35};
int data_length = 15;

void SelectSort() {
	for (int i = 0; i < data_length-1; i++) {
		for (int j = i+1; j < data_length; j++) {
			if (sort_data[j]<sort_data[i]) {
				int temp = sort_data[i];
				sort_data[i] = sort_data[j];
				sort_data[j ] = temp;
			}
		}
	}
}

(3)插入排序
插入排序(Insertion sort)是一种简单直观且稳定的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

算法实质:每步将一个待排序的记录,按其大小插入前面已经排序的序列中适当位置上,直到全部插入完为止。

算法步骤:
(a)指针置于第一个元素,记为已排列元素列的第一位,其余为未排序列;
(b)移动指针到下一个元素,向前依次比较两个元素值的大小;若小于前一位,则交换元素顺序;直至向前移动过程中不能再次交换位置;
(c)重复步骤(b)至排序完成。

C++代码实现:

int sort_data[] = {2,10,15,3,45,1,22,4,50,49,48,27,6,19,35};
int data_length = 15;

void InsertSort() {
	for (int i = 0; i < data_length-1; i++) {
		if (sort_data[i+1]< sort_data[i]) {
			int insert_index = i + 1;
			int current = sort_data[i + 1];
			for (int j = insert_index - 1; j >= 0;j--) {
				if (current<sort_data[j]) {
					int temp = sort_data[j];
					sort_data[j] = current;
					sort_data[j + 1] = temp;
				}
			}	
		}
	}
}

(4)希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
(a)插入排序在对几乎已经排好序的数据操作时,效率高;对反序排列的数据,效果低;
(b)插入排序每次只能将数据移动一位。

算法实质:元素列按增量进行分组,各组进行插入排序。

算法步骤:
(a)按照增量对元素列进行分组。例如数据列{2,10,15,3,45,1,22,4,50,49,48,27,6,19,35},增量为5;则其分组为{2,1,48},{10,22,27},{15,4,6},{3,50,19},{45,49,35}。
(b)各组进行插入排序;
(c)减少增量,重新进行分组,重复步骤(a)和(b)至排序完成。

C++代码实现:

int sort_data[] = {2,10,15,3,45,1,22,4,50,49,48,27,6,19,35};
int data_length = 15;

void HillSort() {
	/*2,1,48
	10,22,27
	....
	45,49,35*/
	for (int k = 5; k > 0;k=k-2) {//增量5,3,1
		for (int i = 0; i < k;i++) {//组号
			for (int p = 1; p < (data_length / k);p++) {//每子组序列元素序列
				if (sort_data[i + p*k] < sort_data[i+(p-1)*k]) {
					int insert_index = i + p*k;
					int current = sort_data[i + p*k];
					for (int j = insert_index - k; j >= 0;j=j-k) {
						if (current < sort_data[j]) {
							int temp = sort_data[j];
							sort_data[j] = current;
							sort_data[j + k] = temp;
						}
					}
				}
			}
		}
	}
}

今天到此为止,后续记录其他排序算法的学习过程。
以上学习笔记,如有侵犯,小白将会立即删除!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南音小榭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值