1、前提

void X_Sort ( ElementType A[], int N )//A是一个数组,N是数组的个数。
  • 大多数情况下,为简单起见,讨论从小大的整数排序
  • N是整数
  • 只讨论基于比较的排序(> = < 有定义)
  • 只讨论内部排序(这里只讨论内存可以装的下的数据量,如果内存装不下,有些数据在磁盘中,则更复杂。)
  • 稳定性:任意两个相等的数据,排序前后的相对位置不发生改变
  • 没有一种排序是任何情况下都表现最好的

2、冒泡排序

#include<iostream>
using namespace std;
typedef int ElementType;

void Bubble_Sort(ElementType A[], int n)
{
	for (int i = n - 1; i >= 0; i--)	//一趟冒泡
	{
		int flag = 0;
		for (int j = 0; j < i; j++)
		{
			if (A[j] > A[j + 1])
			{
				swap(A[j + 1], A[j]);
				flag = 1;	//有元素交换时标识发生变化
			}	
		}
		if (flag == 0)break;	//全程无交换,已经排好序
	}
}

int main()
{
	int a[] = {4,6,1,8,9,3,7,0};
	int len = sizeof(a) / sizeof(a[0]);
	Bubble_Sort(a,len);
	for (int i = 0; i < len; i++)
		cout << a[i] << " ";
	cout << endl;
}

时间复杂度:
最好情况(已经有序,遍历一遍):顺序T = O( N )
最坏情况(逆序):逆序T = O( N2 )

3、插入排序

初始状态下只有一个元素,每插入一个元素,将插入的元素与现有的元素从尾到头比较,将比该元素大的元素依次向后移动,并将该元素插入指定的位置。

#include<iostream>
using namespace std;
typedef int ElementType;

void Insertion_Sort(ElementType A[],int n)
{
	for (int i = 1; i < n; i++)
	{
		int tmp = A[i];
		int j;
		for (j = i; j >0 && A[j-1]>tmp; j--)
			A[j] = A[j - 1];
		A[j] = tmp;
	}
}

int main()
{
	int a[] = {4,6,1,8,9,3,7,0};
	int len = sizeof(a) / sizeof(a[0]);
	Insertion_Sort(a,len);
	for (int i = 0; i < len; i++)
		cout << a[i] << " ";
	cout << endl;
}

最好情况:顺序T = O( N )
最坏情况:逆序T = O( N2 )

4、时间复杂度下界

  • 对于下标i<j,如果A[i]>A[j],则称(i,j)是一对逆序对(inversion)

  • 交换2个相邻元素正好消去1个逆序对!

  • 插入排序:T(N, I) = O( N+I ),I为逆序对数量
    —如果序列基本有序,则插入排序简单且高效

  • 定理:任意N个不同元素组成的序列平均具有N(N-1)/4个逆序对。

  • 定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为Ω(N2)

  • 这意味着:要提高算法效率,我们必须

    • 每次消去不止1个逆序对!
    • 每次交换相隔较远的2个元素!