C語言深入探究選擇排序與基數排序使用案例講解

一.選擇排序

1.1 選擇排序引入

就像炒股一樣,有的人愛炒短線,不斷的買進賣出通過差價來盈利,但是頻繁的買進賣出,也會因為頻繁的手續費和一系列費用獲益較少;有的人,不斷的進行觀察和判斷,等到時機一到,果斷買進或賣出,這種人交易次數少,而最終收獲頗豐;正如我們所說的第一種人就類似排序裡的冒泡排序,而第二種人就在排序中可以理解為:在排序時找到合適的關鍵字再做交換,並且隻交換一次完成相應關鍵字的排序;這就是我們要說的選擇排序。

1.2 選擇排序的基本思想與算法分析

基本思想:從頭至尾掃描序列,找出最小的一個元素,和第一個元素交換,接著從剩下的元素中繼續這種選擇和交換方式,最終得到一個有序序列

算法分析:

  1. 第1步:在未排序的n個數(a [0] ~a [n- 1])中找到最小數,將它與a [0]交換;
  2. 第2步:在剩下未排序的n- 1個數(a [1] ~a [n- 1])中找到最小數,將它與a[1]交換;
  3. 第n-1步:在剩下未排序的2個數(a [n-2] ~a [n- 1] )中找到最小數,將它與a [n-2]交換;
  4. 得到一個排好序的序列。

1.3 實例說明

以12,32,2,60,42,98為例,排序過程如下:

  • 數字底下有橫線的為已排好序的
  • n個值排n-1次即可
  • 每一次都找一個最小值放到前面

1.4 代碼實現

代碼如下:

void SelectSort(int arr[], int len)
{
	for (int i = 0; i < len - 1; i++)//趟數
	{
		int min_index = i;
		for (int j = i + 1; j < len; j++)//控制找最小值
		{
			if (arr[j] < arr[min_index])
			{
				min_index = j;
			}
		}
		//當內層for循環跑完,此時min_index保存是就是當前待排序序列中最小值的下標
		if (min_index != i)//如果找到的最小值下標  不等於 待排序序列的第一個值的下標  則才有交換的必要性
		{
			int tmp = arr[i];
			arr[i] = arr[min_index];
			arr[min_index] = tmp;
		}
	}
}

1.5 性能分析

  • 時間復雜度:O(n^2)。
  • 空間復雜度:O(1)。
  • 穩定性:不穩定。

盡管與冒泡排序的時間復雜度同為O(n^2),但選擇排序的性能還是略優於冒泡排序的。

二.基數排序

2.1 基數排序基本思想與算法步驟

基本思想:將整數按位數切割成不同的數字,然後按每個位數分別比較,最後合並結果。

算法步驟:

  • 將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零;
  • 從最低位開始,依次進行一次排序;
  • 從最低位排序一直到最高位排序完成以後, 整合後數列就變成一個有序序列。

2.2 實例說明

以12,32,2,620,42,98,122,289,987,37,56,90為例,排序過程如下:

1.以個位數跑一趟:

個位排序的最終結果:

620,90,12,32,2,42,122,56,987,27,98,289

(這些數據隻看個位的話為有序)

2.以十位跑一趟:

十位排序的最終結果:

2,12,620,122,27,32,43,56,987,289,90,98

(這些數據隻看十位的話為有序)

3.以百位跑一趟:

百位排序的最終結果:

2,12,27,32,43,56,90,98,122,289,620,987

(數據已完全有序)

2.3 代碼實現

代碼如下:

//獲取數組中最大值的位數
int Get_figure(int* arr, int len)
{
	int max = 0;
	for (int i = 0; i < len; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	int count = 0;
	while (max != 0)
	{
		count++;
		max /= 10;
	}
	return count;
}
//這個函數告訴我傳進來的參數n的,對應fin位是多少
//1234,2 -> 2    345,1 ->4    0078,3 -> 0     56789,4 -> 5
int Get_Num(int n, int fin)
{
	for (int i = 0; i < fin; i++)//這裡代表需要n 先丟幾位最低位
	{
		//n = n/10;
		n /= 10;
	}
	return n % 10;//此時獲取剩餘屬於的最低位即可
}
//一趟桶排序    fin代表這一趟是根據哪個位進行排序(個,十,百......)   0->個位  1->十位...
void Radix(int* arr, int len, int fin)//時間復雜度O(n)
{
	//先將10個桶申請好
	int bucket[10][100] = { 0 };
	int num[10] = { 0 };  //num[1] 代表1號桶中有多少個有效值
	//將所有數據從左向右向對應的桶中存放
	for (int i = 0; i < len; i++)
	{
		int index = Get_Num(arr[i], fin);
		bucket[index][num[index]] = arr[i];
		num[index]++;
	}
	//按照0->9號桶的順序,依次遵循先進先出的規則將所有值取出來
	int k = 0;
	for (int i = 0; i <= 9; i++)//0->9號桶依次取
	{
		for (int j = 0; j < num[i]; j++)//對應的桶內,從上到下依次取值
		{
			arr[k++] = bucket[i][j];//取出來的值 從前向後放到arr中
		}
	}
}
//基數排序(桶排序)  時間復雜度(d*n)(假設最大值的位數是d) 空間復雜度O(d*n) 穩定性:穩定
void RadixSort(int* arr, int len)
{
	//assert
	//1.首先需要知道 數據中最大值有多少位
	int count = Get_figure(arr, len);

	for (int i = 0; i < count; i++) //D
	{
		Radix(arr, len, i);
	}
}

2.4 性能分析

假設最大值的位數是d

  • 時間復雜度:O (d*n)。
  • 空間復雜度:O (d*n)。
  • 穩定性:穩定。

到此這篇關於C語言深入探究選擇排序與基數排序使用案例講解的文章就介紹到這瞭,更多相關C語言排序內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: