排序方法总结(稳定性和复杂度问题)
文章目录
前言
数据结构期末考试啦,要将各种排序方法进行分析,复杂度问题和稳定性问题,那就在此总结一下啦,希望能够帮助到在看这篇文章的你!( ^ - ^ )!
稳定性
所谓稳定性,通俗的来说就是如果一个数组中有两个相等的数字,arr[i]=arr[j],i<j,且通过排序后仍然有i<j。即相等的两个数没有进行交换,就称这个排序为稳定的。
时间复杂度
所谓时间复杂度就是整个算法程序所使用的时间,通常根据循环来计算。
一、直接插入法排序
思路分析:(根据排序方法名称来看,这是一个十分暴力的方法。)实质上就是在原有的数组的基础上从第二个数字开始向后遍历一遍(这里用到的是后面的与前面的比较,防止下标越界,就从第二位开始遍历),如果遇到了后面的数字(记为temp=arr[i])小于前面的数arr[i-1],就开始向前找,知道找到不小于temp。并且每次向前查找的时候将此次的数字向后移动一位,最后将现在的数字插入到它应该在的位置。实质上i前面可以看成有序部分,后面可以看成无序部分。
可能有些晕了叭,那就来看分析图好啦><!
再来分析代码:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
//直接插入排序
void Directinsertionsort(int a[],int length)
{
int i, j;
for (i = 1; i < length; i++){
int temp = a[i];
for (j = i; (j > 0) && (a[j - 1] > temp); j--)//边界问题,j也不能越界!
{
a[j] = a[j - 1];
}
a[j] = temp;
}
}
int main()
{
int n;
cin >> n;
int arr[N];
for (int i = 0; i < n;i++)
cin >> arr[i];
Directinsertionsort(arr, n);
for (int i = 0; i < n;i++)
cout << arr[i] << " ";
cout << endl;
return 0;
}
稳定性:稳定;时间复杂度:O(n2)
二、折半插入法排序
思路分析:二分思想,不用过多解释。(每次从i前面数列的中间比较,逐步缩小范围,直到找到应该插入的位置,最后将插入位置后到i所有的数字向后移动,最后插入数字。)
见图分析:
分析代码:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
//折半插入法排序
void Splitinsertionsort(int a[],int length)
{
for (int i = 1; i < length;i++){
int temp = a[i];
int left = 0, right = i - 1;
while(left<=right){
//二分经典模板(依旧是前面有序后面无序)
int mid = (left + right) / 2;
if(temp<a[mid])
right = mid - 1;
else
left = mid + 1;
}
for (int k = i - 1; k >= left;k--)
a[k + 1] = a[k];
a[left] = temp;
}
}
int main()
{
int n;
cin >> n;
int arr[N];
for (int i = 0; i < n;i++)
cin >> arr[i];
Splitinsertionsort(arr, n);
for (int i = 0; i < n;i++)
cout << arr[i] << " ";
cout << endl;
return 0;
}
稳定性:稳定;复杂度:O(n2)
三、希尔排序
思路分析:从一开始,将数组内的数字分为几个小组,间距相同的在一个小组内,通常将距离设置为原数组长度的一半。eg.若间距为4,则数据1,5,9…为一组,2,6,10…为一组,3,7,11…为一组,4,8,12…为一组。然后进行组内的直接插入排序,第一次执行结束后就将间距缩小一半再次进行操作,一直循环此步骤,直到间距为1时成为了整个数组为一组进行直接插入排序结束后就得到了最终需要的数组。
来分析代码:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
//希尔排序
void Shellsort(int a[], int length)
{
int gap = length / 2;//初始间距
while (gap)
{
for (int start = gap; start < 2 * gap && start < length; start++)
{
for (int i = start; i < length; i += gap)//组内直接插入排序
{
int temp = a[i];
int j = i;
while (j >= gap && temp < a[j - gap])
{
a[