排序2—交換排序

前言:

     我們還是老規矩,先看看交換排序的基本思想:兩兩比較待排序記錄的關鍵字,一旦發現兩個記錄不滿足此需要求時則進行交換,知道整個序列全部滿足要求爲止。是不是一想到這個就想起來最簡單最先接觸的冒泡排序呢?

一、冒泡排序

     冒泡排序是一種最簡單的交換排序方法,它通過兩兩比較相鄰記錄的關鍵字,如果發生逆序,則進行交換,從而使關鍵字小的記錄如氣泡一般逐漸往上“漂浮”,或者“墜落”(這個理解就是從後往前,和從前往後比較的區別)。
     但是機智的你又會發現,很多時候如果我的序列基本有序或者就是有序的,我的冒泡算法還是會依次的進行查找操作,雖然沒有進行移動,但是也浪費了時間。所以這裏我給出的算法就設置了標誌flag,當我沒有發生移動時,那麼就說明已經有序了,不需要在進行循環操作了。
【算法描述】

void BubbleSort(SqList &L)
{
	//對順序表L做冒泡排序
	int m,j,flag;
	ElemType t;
    m=L.length-1; flag=1; 				//flag用來標記某一趟排序是否發生交換
    while((m>0)&&(flag==1))
	{
		flag=0;           				//flag置爲0,如果本趟排序沒有發生交換,則不會執行下一趟排序
        for(j=1;j<=m;j++)
			if(L.r[j].key>L.r[j+1].key) 
			{
				flag=1;					//flag置爲1,表示本趟排序發生了交換
				t=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=t;	//交換前後兩個記錄
			}							//if
		--m;
    }									//while
}				


二、快速排序(這個可厲害了,同數量級中平均複雜度是最好的)

     機智的你還發現了,冒泡排序穩定,簡單,但是我們還是要追求速度,如果我們可以一次就可以消除多個逆序,是不是更快了呢?
     我把這個快速排序稱之爲“歡快的跳躍”,因爲我是從兩頭逼近式的查找。
【算法描述】
     自己歸納一下就是首先確定樞軸,然後我們想要得到的就是,樞軸的左邊比樞軸小,右邊比樞軸大。從前往後,找到了交換位置,一直重複。最後就可以得到有序序列了。(哈哈,至於這個具體的概念,大家可以查找)。但是在看概念的時候,就記住,以樞軸爲中心,不滿足前面比我小,後面比我大就交換位置,從後往前找,交換了在從前往後找,依次操作。計算時間的複雜度相對於冒泡優化了很多。
你看這個圖,就這樣演示操作的:
在這裏插入圖片描述
從前往後,從後往前,最後就得到了有序序列。
程序演示會讓你清晰很多哦


快速排序的程序演示:

//快速排序
#include <iostream>
using namespace std;
#define  MAXSIZE  20          			//順序表的最大長度
typedef struct
{
	int key;
	char *otherinfo;
}ElemType;
//順序表的存儲結構                         
typedef struct
{
    ElemType *r;	         						//存儲空間的基地址
    int  length;            						//順序表長度
}SqList;											//順序表類型
int Partition(SqList &L,int low,int high)
{ 
	//對順序表L中的子表r[low..high]進行一趟排序,返回樞軸位置
	int pivotkey;
	L.r[0]=L.r[low];                    	//用子表的第一個記錄做樞軸記錄
	pivotkey=L.r[low].key;		   			//樞軸記錄關鍵字保存在pivotkey中
	while(low<high)
	{										//從表的兩端交替地向中間掃描
		while(low<high&&L.r[high].key>=pivotkey) --high;
		L.r[low]=L.r[high];					//將比樞軸記錄小的記錄移到低端
		while(low<high&&L.r[low].key<=pivotkey) ++low;
		L.r[high]=L.r[low];					//將比樞軸記錄大的記錄移到高端
	}//while
	L.r[low]=L.r[0];						//樞軸記錄到位
	return  low;							//返回樞軸位置
}//Partition
void QSort(SqList &L,int low,int high)
{	//調用前置初值:low=1; high=L.length;
    //對順序表L中的子序列L.r[low..high]做快速排序
	int pivotloc;
    if(low<high)
	{										//長度大於1
       pivotloc=Partition(L,low,high); 		//將L.r[low..high]一分爲二,pivotloc是樞軸位置
       QSort(L,low,pivotloc-1);				//對左子表遞歸排序
       QSort(L,pivotloc+1,high);        	//對右子表遞歸排序
	}
}											//QSort
void QuickSort(SqList &L)
{
   //對順序表L做快速排序
   QSort(L,1,L.length);
}											//QuickSort								
void Create_Sq(SqList &L)
{
	int i,n;
	cout<<"請輸入數據個數,不超過"<<MAXSIZE<<"個。"<<endl;
	cin>>n;											//輸入個數
	cout<<"請輸入待排序的數據:\n";
	while(n>MAXSIZE)
	{
		cout<<"個數超過上限,不能超過"<<MAXSIZE<<",請重新輸入"<<endl;
		cin>>n;
	}
	for(i=1;i<=n;i++)
	{
		cin>>L.r[i].key;
		L.length++;
	}
}
void show(SqList L)
{
	int i;
	for(i=1;i<=L.length;i++)
		cout<<L.r[i].key<<endl;
}
void main()
{
	SqList L;
	L.r=new ElemType[MAXSIZE+1];
	L.length=0;
	Create_Sq(L);
	QuickSort(L);
	cout<<"排序後的結果爲:"<<endl;
	show(L);
}


後記:

     那麼交換排序就結束啦,之後預告選擇排序。如有誤,評論指出哦,謝謝。

發佈了85 篇原創文章 · 獲贊 189 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章