1. 程式人生 > >簡單排序——氣泡排序,插入排序,逆序對

簡單排序——氣泡排序,插入排序,逆序對

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個元素!