1. 程式人生 > >【內部排序】 交換排序與選擇排序詳解

【內部排序】 交換排序與選擇排序詳解

交換排序:通過依次交換逆序的元素使其有序化的過程。

介紹兩種交換排序: 氣泡排序,快速排序

冒泡法:從第一個元素開始,依次比較相鄰的兩個元素,如果逆序則交換,第一趟比較結束後,序列中最大的元素將移動到序列末尾,即第n個位置,第二趟將次大元素移動到n-1位置…… 多趟比較後,會形成有序序列,排序方法類似氣泡慢慢向上浮動,因此成為冒泡法。

快速排序: 對冒泡的改進,將序列中的關鍵字和指定元素(樞軸)比較,將序列以樞軸劃分,保證樞軸大於其左邊所有數,小於其右邊所有數

樞軸的選取很關鍵,避免快排在區域性有序數列中退化,再次使用的三者取中法)

按照以上方法,對上次劃分的子序列進行遞迴劃分,知道每個子序列只剩下一個元素不能劃分為止,此時序列有序。

程式碼實現:

#include<iostream>
#define SIZE 21  
typedef int Sqlist[SIZE];

using namespace std;

void swap(int &a, int &b)
{
	a = a^b;
	b = a^b;
	a = a^b;
}

//==================================BubbleSort()==================================
/// @brief <對函式進行概括說明>	氣泡排序 
/// 
/// <對函式進行詳細說明>	內部排序,穩定排序,交換排序 時間複雜度:平均 O(n),最壞O(n^2)
///
/// @param [in, out] sq <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇> 陣列
/// @param [in, out] n <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>  陣列大小
///
/// @return <返回值說明,可以配合使用DocGenList或DocGenTable>	無返回值
///
/// @remark <函式特別說明>	使用引用
///
/// @code
///      <在此新增示例程式碼>
/// @endcode
void BubbleSort(Sqlist &sq, int n)
{
	cout << "氣泡排序:" << endl;
	for (int i = 0; i < n - 1; ++i)
	{
		for (int j = 0; j < n - i - 1; ++j)
		{
			if (sq[j] > sq[j + 1])
			{
				swap(sq[j],sq[j+1]);
			}
		}
	}
}
/////////////////////////////////////////////////////

//================================PivotkeySelect()================================
/// @brief <對函式進行概括說明> 樞軸選取
///
/// <對函式進行詳細說明>		三者取中  
///
//================================================================================
int PivotkeySelect(Sqlist &sq, int low, int high)
{
	int mid = low + ((high - low) >> 1);//計算陣列中間的元素的下標  

	//使用三數取中法選擇樞軸  
	if (sq[mid] > sq[high])//目標: sq[mid] <= sq[high]  
	{
		swap(sq[mid], sq[high]);
	}
	if (sq[low] > sq[high])//目標: sq[low] <= sq[high]  
	{
		swap(sq[low], sq[high]);
	}
	if (sq[mid] > sq[low]) //目標: sq[low] >= sq[mid]  
	{
		swap(sq[mid], sq[low]);
	}
	//此時,sq[mid] <= sq[low] <= sq[high]  
	return sq[low];
	//low的位置上儲存這三個位置中間的值  
	//分割時可以直接使用low位置的元素作為樞軸,而不用改變分割函數了
}

//==================================Partition()=================================
/// @brief <對函式進行概括說明> 劃分
///
/// <對函式進行詳細說明> 用樞軸將陣列劃分
///
/// @sa <可以參考的類或函式,用空格分隔,函式名稱後必須加()> PivotkeySelect()
//================================================================================
int Partition(Sqlist &sq, int low, int high)
{
	int key = PivotkeySelect(sq,low,high);					//輔助空間
	
	while (low < high)
	{
		while (low < high && sq[high] >= key)
		{
			high--;
		}
		sq[low] = sq[high];

		while (low < high && sq[low] <= key)
		{
			low++;
		}
		sq[high] = sq[low];
	}
	sq[low] = key;
	return low;
}

//==================================QuickSort()=================================
/// @brief <對函式進行概括說明> 快速排序	對冒泡的改進 不穩定
///
/// <對函式進行詳細說明>	將關鍵字與指定元素比較 遞迴 時間複雜度:平均O(nlog2^n) 最壞O(n^2)
///
/// @param [in, out] sq <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇> 陣列
/// @param [in, out] low <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇> 最小下標
/// @param [in, out] high <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇> 最大下標
///
/// @return <返回值說明,可以配合使用DocGenList或DocGenTable>  返回low
///
/// @remark <函式特別說明>
///
/// @code
///      <在此新增示例程式碼>
/// @endcode
///
/// @sa <可以參考的類或函式,用空格分隔,函式名稱後必須加()> Partition() PivotkeySelect()
//================================================================================
void QuickSort(Sqlist &sq, int low, int high)
{
	if (low < high)
	{
		int prvitloc = Partition(sq, low, high);     //將陣列一分為二  
		QuickSort(sq, low, prvitloc - 1);              //左半部分排序  
		QuickSort(sq, prvitloc + 1, high);
	}
}

選擇排序:

對於n個元素的序列,第一趟經n-1此比較,選出最小的放在第一個位置,第二趟從n-1個元素中,經過n-2次比較,選出最小的放在第二個位置……直到沒有待比較的元素。

程式碼實現:

//====================================MinKey()====================================
/// @brief <對函式進行概括說明> 最小值選取
///
/// <對函式進行詳細說明> 從key位置開始,找出大小為n陣列中的最小值,並返回下標
///
/// @param [in, out] sq <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>
/// @param [in, out] n <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>
/// @param [in, out] key <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>
///

//================================================================================
int MinKey(Sqlist &sq, int n, int key)
{
	int k = key + 1;
	for (; k < n; ++k)
	{
		if (sq[k] < sq[key])                         //若小於則記錄下標  
		{
			key = k;
		}
	}
	return key;
}


//==================================SelectSort()==================================
/// @brief <對函式進行概括說明> 簡單選擇排序
///
/// <對函式進行詳細說明> n個元素,第一次n-1次比較,選出n箇中最小元素,放在序列最前面
///
/// @param [in, out] sq <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>
/// @param [in, out] n <引數說明,[in, out]表示引數的傳遞方向,需要根據情況進行選擇>
///
/// @return <返回值說明,可以配合使用DocGenList或DocGenTable> 
///
/// @remark <函式特別說明>
///
/// @code
///      <在此新增示例程式碼>
/// @endcode
///
/// @sa <可以參考的類或函式,用空格分隔,函式名稱後必須加()> MinKey() swap()
//================================================================================
void SelectSort(Sqlist &sq, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int j = MinKey(sq, n, i);
		if (i != j)
			swap(sq[i],sq[j]);
	}
}

測試程式:
void main(void)
{
	Sqlist sq = { 49, 38, 65, 97, 76, 13, 27, 49 };
	Sqlist sq2 = { 49, 38, 65, 97, 76, 13, 27, 49 };
	Sqlist sq3 = { 49, 38, 65, 97, 76, 13, 27, 49 };
	cout << "原陣列為:" << endl;
	
	for (int i = 0; i < 8; ++i)
	{
		cout << sq[i]<<" ";
	}
	cout << endl;
////////////////////////////////////////////
	BubbleSort(sq,8);

	for (int i = 0; i < 8; ++i)
	{
		cout << sq[i] << " ";
	}
	cout << endl;
/////////////////////////////////////////////
	cout << "原陣列為:" << endl;

	for (int i = 0; i < 8; ++i)
	{
		cout << sq2[i] << " ";
	}
	cout << endl;

	QuickSort(sq2, 0, 7);
	cout << "快速排序:" << endl;
	for (int i = 0; i < 8; ++i)
	{
		cout << sq2[i] << " ";
	}
	cout << endl;
	//////////////////////////////////////
	cout << "原陣列為:" << endl;

	for (int i = 0; i < 8; ++i)
	{
		cout << sq3[i] << " ";
	}
	cout << endl;

	SelectSort(sq3, 8);
	cout << "交換排序:" << endl;
	for (int i = 0; i < 8; ++i)
	{
		cout << sq3[i] << " ";
	}
	cout << endl;
}



相關推薦

Java深入深拷貝淺拷貝

1.拷貝的引入 (1)引用拷貝 建立一個指向物件的引用變數的拷貝。 例1: Teacher teacher = new Teacher("Taylor",26); Teacher otherteacher = teacher; System.out.

必須知道的八大種排序演算法java實現(二) 選擇排序,插入排序,希爾演算法

一、選擇排序   1、基本思想:在要排序的一組數中,選出最小的一個數與第一個位置的數交換;然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後一個數比較為止。   2、例項   3、演算法實現    /** * 選擇排序演算法 * 在未

陣列排序交換選擇法)

交換法與選擇法降序排序 交換法 交換法對陣列陣列進行排序的基本思路 就是先讓陣列(n個數)中的最左邊的一個數(用i=0代表)與其右邊的每一個數(從j=i+1開始)依次(j++)進行比較,若遇到比其大的數(score[j]>score[i]),則將較

氣泡排序簡記以及其選擇排序的區別

氣泡排序 所謂的氣泡排序,其基本概念是,依次比較相鄰兩個數的大小,如果num[i] > num[i+1],則將小數放在前面,大數放在後面。如此繼續,直至比較最後兩個數,將小數放前,大數放後。至此

機器學習模型評估選擇

內容大多來自 統計學習方法——李航 機器學習——周志華 1. 統計學習三要素   統計學習方法都是有模型、策略和演算法構成的,也就是統計學習方法由三要素構成,可以簡單地表示為: 方法=模型+策略+算法方法=模型+策略+算法 構建一種統計學習方法就是

Mint-UIsearch元件的使用及(內含取消事件的觸發)

用過Mint-UI的同學都知道,Mint-UI的文件寫的極簡,剛接觸的同學難免會因為文件不夠詳細而暈頭轉向無法下手(日常吐槽) 由於專案的需要,入坑了mint-ui的search元件,文件寫的果然讓人摸不到頭腦。 下邊直接看效果: 我們開發的是基於微信瀏覽器的移動端專案,該圖是

深度學習GAN生成對抗網路原理(1)

一個 GAN 框架,最少(但不限於)擁有兩個組成部分,一個是生成模型 G,一個是判別模型 D。在訓練過程中,會把生成模型生成的樣本和真實樣本隨機地傳送一張(或者一個 batch)給判別模型 D。判別模型 D 的目標是儘可能正確地識別出真實樣本(輸出為“真”,或者1),和儘可能

python基礎os.path模組常用方法

os.path模組 主要用於檔案的屬性獲取,在程式設計中經常用到,以下是該模組的幾種常用方法。 更多的方法可以去檢視官方文件:http://docs.python.org/library/os.path.html 參考:https://www.cnblogs.com/wuxie1989/p/562343

CSS入門之樣式表選擇

    CSS用來定義HTML頁面中文字顯示樣式,還有類、層等特性,還可以對文字重疊、定位等。引入CSS到HTML中,主要是因為在傳統的HTML上控制文字顯示樣式和版面非常難,引入CSS之後,控制方式變得簡單,頁面也變得更加美觀、豐富。     所以CSS主要就是用來提供樣

強化學習Deep Q Network(DQN)演算法

 原文地址:https://blog.csdn.net/qq_30615903/article/details/80744083 DQN(Deep Q-Learning)是將深度學習deeplearning與強化學習reinforcementlearning相結合,實現了從

軟考原碼, 反碼, 補碼

本篇文章講解了計算機的原碼, 反碼和補碼. 並且進行了深入探求了為何要使用反碼和補碼, 以及更進一步的論證了為何可以用反碼, 補碼的加法計算原碼的減法. 論證部分如有不對的地方請各位牛人幫忙指正! 希望本文對大家學習計算機基礎有所幫助! 一. 機器數和真值 在學習原碼, 反碼和補碼之前, 需要先了解

Oracle 11gR2靜默安裝 db_install.rsp檔案

#################################################################### ## Copyright(c) Oracle Corporation1998,2008. All rights reserved. ## ##

目標檢測SSD演算法--損失函式的(tensorflow實現)

SSD的損失函式包含用於分類的log loss 和用於迴歸的smooth L1,並對正負樣本比例進行了控制,可以提高優化速度和訓練結果的穩定性。 總的損失函式是分類和迴歸的誤差的帶權加和。α表示兩者的權重,N表示匹配到default box的數量 1 loc的損失函式

文字檢測SSD+Tensorflow 300&512 配置

SSD_300_vgg和SSD_512_vgg weights下載連結【需要科學上網~】: Model Training data Testing data mAP FPS VOC07+12+COCO trainval VOC07

知識普及PostScript中的“命名資源”

PS檔案中的“命名資源”(Named Resources)            作者:bobob     日期:2007.12.11           ps中的一些特性是用一組object的集合來控制的。比如font,可以用一個字典來描述字元的外形。在ps levle2

U-Net語義分割之U-Net

一、簡介   語義分割(Semantic Segmentation)是影象處理和機器視覺一個重要分支。與分類任務不同,語義分割需要判斷影象每個畫素點的類別,進行精確分割。語義分割目前在自動駕駛、自動摳圖等領域有著比較廣泛的應用。 分割網路現狀:   在Re

機器學習5種距離度量方法+Python實現([]+lambda+np.frompyfunc+向量法等多種方法實現)

介紹的五種距離度量方法是:歐氏距離(Euclidean Distance),曼哈頓距離(Manhattan Distance),夾角餘弦(Angle Cosine),切比雪夫距離(Chebyshev Distance),漢明距離(Hamming Distance)。1.歐式距

機器學習最大均值差異MMD

引言 最大均值差異(maximum mean discrepancy, MMD)提出時候是用來測試兩個樣本,是否來自兩個不同分佈p和q,如果均值差異達到最大,就說明取樣的樣本來自完全不同的分佈。 原理 MMD的基本原理如下所述:假設有一個滿足P分佈的資料集Xs=[xs1,...,xsn]

生成樹RSTP (802.1W)協議機制

    看上圖,初始情況下,C的一個介面被選舉為非指定埠被Block,B會從指定埠傳送BPDU給C。我們先考慮一下802.1D的情況,當Root及B之間的鏈路故障了,由於C上連線B的介面被BLOCK,它不傳送BPDU給B,因此,B此刻認為自己是Root,於是向C傳送自己為Root的BPDU。而由於這個時候C的

深度學習Torch卷積層原始碼

本文以前向傳播為例,詳細分析Torch的nn包中,SpatialConvolution函式的實現方式。 在分析原始檔時,同時給出了github上的連結以及安裝後的檔案位置。 初始化 定義一個卷積層需要如下輸入引數 nInputPlane\nOutpu