排序算法的知识

引言:

主要介绍几个排序以及各自的优缺点,方便大家更好理解排序算法

一、冒泡排序

1、概念:

就是通过相邻元素的比较和交换,将较小的元素逐步"冒泡"到数组前端。

2、步骤(升序为例):

a、遍历数组,从第一个元素开始比较,依次比较相邻的两个元素。

b、交换元素:如果前一个元素比后一个元素大的话,就交换。

c、重复步骤b直到整个数组都有序。

3、注意点:

循环的次数是n-1,因为每一次循环,都是将一个元素排到后面去,避免影响前面

的排序。那么你一共要排n-1个元素。因为你后面的元素都排好了,第一个元素也就正确了

啊。

4、代码:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
BubbleSort(vector<int>& vec)
{
	for (int i = vec.size()-1; i >= 1; i--)
	{
		bool flag = true;//优化
		for (int j = 0; j < i; j++)
		{
			if (vec[j] > vec[j + 1])
			{
				swap(vec[j], vec[j + 1]);
				flag = false;
			}
		}
		if (flag) break;//如果flag执行一次循环还是为true,则说明已经排好序,直接跳出即可
	}
}
int main()
{
	vector<int> vec= { 10,12,2423,546,767,1,4,5,345,124 };
	cout << BubbleSort(vec);
	return 0;
}

为什么是从i=vec.szie()-1开始呢?因为你最先排好的最后一个呀。那么你后续的循环是

排序排除排好的数字了。

加flag进行判断是为了提前结束,避免浪费时间和空间。

二、选择排序

三、插入排序

1、概念:

就是将未排序好的元素逐个插入到已排序的序列中的合适位置。其实就跟你整理书籍一样,把书本放到已经排好序的书籍中的合适位置。

2、步骤:

a、选择数组的第一个元素作为已排序部分,剩余的就开始挨个插入。

b、从未排序的数组开始,逐个去除,跟已排序的部分从前往后开始比较。

c、重复步骤b直到数组有序。

3、注意:

就是需要替换,因为你排好序的数组的当前位置是有元素的,当这个位置有新元素

来,那么你从这个位置开始的后面元素都得往后移动。

4、代码:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
void InsertSort(vector<int>& vec)
{

	for (int j = 1; j < vec.size(); j++)//无序区间段
	{
		for (int i = 0; i < j; i++)//有序区间段
		{
			if (vec[i] > vec[j])
			{
				int temp = vec[j];
				for (int k = j-1; k>=i; k--)
				{
					vec[k + 1] = vec[k];
				}
				vec[i] = temp;
			}
		}
	}
}
int main()
{
	vector<int> vec= { 10,12,2423,546,767,1,4,5,345,124 };
	cout << InsertSort(vec);
	return 0;
}

值得注意的就是你的后移,得把当前vec[j]空出来存放vec[i]。后移不会溢出是因为你的j最大

就是vec.size()-1。

四、希尔排序

1、概念:

改进的插入排序。插入是直接整个数组进行,而希尔排序则是分组进行排序,然后逐步缩短每个数组的长度,直到长度为1,

2、步骤:

a、首先选择一个间隔,就是每个子数组的长度。一般是n/2。

b、然后根据间隔,将数组分隔为多个子数组。

c、然后对每个子数组进行插入排序。

d、逐步减小间隔,直到间隔为1。

3、注意:

按照间隔是将数组分成若干个子数组,但是不是说均分,而是说按照间隔大小来

分。

比如数组长度是10,间隔是3。

那么分出的第一个数组:0,3,6,9

第二个数组:1,4,7

第三个数组:2,5,8

分的是下标,以及数组个数。而不是直接均分。

4、代码:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
void InsertShell(vector<int>& vec, int start, int gap)
{
	for (int i = gap + start; i < vec.size(); i += gap)
	{
		for (int j = start; j < i; j += gap)
		{
			if (vec[i] < vec[j])
			{
				int temp = vec[i];
				for (int k = i - gap; k >= j; k-=gap)
				{
					vec[k + gap] = vec[k];
				}
				vec[j] = temp;
			}
		}
	}
}
void ShellSort(vector<int>& vec)
{
	for (int gap = vec.size() / 2; gap >= 1; gap /= 2)
	{
		for (int i = 0; i < gap; i++)
		{
			InsertShell(vec, i, gap);
		}
	}
}
int main()
{
	vector<int> vec= { 10,12,2423,546,767,1,4,5,345,124 };
	cout << ShellSort(vec);
	return 0;
}

如果观察仔细的话,其实插入排序其实就是间隔为1的希尔排序。

五、计数排序

六、桶排序

七、堆排序