1. 程式人生 > >簡單排序演算法之簡單選擇排序和直接插入排序

簡單排序演算法之簡單選擇排序和直接插入排序

簡單選擇排序簡述:

簡單選擇排序(Simple Selection Sort)可以說是氣泡排序的一種改版,它不再兩兩比較出較小數就進行交換,而是每次遍歷比較當前數的後面所有數,最後再把最小的數和當前數進行交換。

排序前的準備:

#define MAXSIZE 10
//順序表結構
template <class T>
struct SqList
{
	T s[MAXSIZE + 1] = { NULL, 98, 24, 55, 81, 32, 77, 48, 60, 14, 8 };          //陣列s,s[0]用作哨兵
	int length = MAXSIZE;              //s長度
	void PrintArray();
};
typedef SqList<int> SList;

//交換l中的陣列中下標為i和j的值
void Swap(SList *L, int i, int j)
{
	int temp = L->s[i];
	L->s[i] = L->s[j];
	L->s[j] = temp;
}

template <class T>
void SqList<T>::PrintArray()
{
	for (int i = 1; i <= MAXSIZE; i++)
	{
		cout << s[i] << " ";
	}
	cout << endl;
}

簡單選擇排序的實現:

//簡單選擇排序
//每次和後面所有的元素進行比較,選出最小的元素,進行交換。
void SelectSort(SList *L)
{
	int i, j, min;
	for (i = 1; i < L->length; i++)
	{
		min = i;    //一開始預設最小元素下標的為自身下標
		for (j = i + 1; j <= L->length; j++)
		{
			//遍歷尋找最小元素
			if (L->s[min] > L->s[j])         //如果存在比現在最小元素小的元素
			{
				min = j;    //改變最小元素下標
			}
		}
		//找到最小元素
		if (i != min)    //找到的元素不是原來的
		{
			Swap(L, i, min);    //交換元素
		}
	}
}

簡單選擇排序的時間複雜度:

簡單選擇排序無論最好最壞情況都要比較的次數一樣=1+2+3+...+(n-1)=(n(n-1))/2,即O(n^2)

但簡單選擇排序的交換的次數較少,所以相對氣泡排序效率更高。

直接插入排序簡述:

直接插入排序(Straight Insertion Sort)換了一種思路,它把一個元素插入一個有序表的適當位置,從而得到一個新的長度加一的有序表。

直接插入排序實現:

//直接插入排序
//將一個新的元素插入一個有序表的適當位置,得到一個新的長度加一的有序表
void InsertSort(SList *L)
{
	int i, j;
	for (i = 2; i <= L->length; i++)    //i從2開始,預設s[1]為一個有序表,s[0]作為哨兵位置
	{
		if (L->s[i] < L->s[i-1])      //如果要比較i比前一位小則進行插入,如果比前一位元素大則不進行插入
		{
			L->s[0] = L->s[i];       //把哨兵位置賦值為要插入的數
			//將比哨兵大的元素都進行後移操作,來空出位置進行插入
			for (j = i - 1; L->s[j] > L->s[0]; j--)
			{
				L->s[j + 1] = L->s[j];
			}
			//最後將空位賦值為要插入的數,即哨兵的值
			L->s[j + 1] = L->s[0];
		}
	}
}

直接插入排序的時間複雜度:

最好情況:本身表就是有序的,每個後面的數和前面的進行一次比較,即時間複雜度為O(n);

最壞情況:表為逆序,所以要比較的次數=2+3+4+..+n=((n+2)(n-1)/2,即時間複雜度為O(n^2),

雖然時間複雜度都為O(n^2),但直接插入排序的效率比簡單選擇排序和氣泡排序都要好一點。