各種排序算法的實現與總結(一)

       前段時間,由於有些事情的耽誤,還有就是自己有點懶,所以很久沒有寫博客了,今天打算給大家帶來數據結構中的常見問題——排序,同時這也是面試中經常被問到的部分,因此今天決定對各種排序算法進行自我梳理一遍,以此鞏固自己的基礎。

       排序算法常見的有:冒泡排序,選擇排序,直接插入排序,希爾排序,歸併排序,快速排序,堆排序,基數排序這八種排序算法,主要從時間複雜度、空間複雜度、穩定性、是否與初始的次序有關等方面來評價該排序算法的優劣。

            以上四點判斷,其實只要真正明白了其算法思想,按照其流程走,不難分析出其中的緣由。網上分析其思想原理的資料太多,我在此就不在贅述了。直接給出C++代碼實現,以供大家參考,大家有什麼建議和意見,可以直接留言或私信。

"sort_algorithms.h":

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
//冒泡排序
void bubble_sort(int *, int n );

//選擇排序
void choose_sort(int *, int n);

//插入排序
void insert_sort(int *, int n);

//希爾排序
void  shell_sort(int *, int n);

//歸併排序
void merge_sort(int *, int begin, int end, int *);
void merge_array(int *,int begin, int mid, int end, int *);
void MergeSort(int *, int n); 

//快速排序
void quick_sort(int *, int begin, int end);
void QuickSort(int *, int n);

//顯示輸出數組
void display(int *arr, int n);

//隨機產生1-n的整數
long random(long n);


"sort_algorithms.cpp":

#include"sort_algorithms.h"

//冒泡排序
void bubble_sort(int  *arr, int n)
{
	if( NULL == arr ||n < 1)
		return;
	int temp;
	//因爲冒泡排序的效率和數組初始化的次序有關,用來判斷後面的是否已經排好序,以便直接退出,提供效率
	bool isOver = true;
	for(int i = 0; i < n - 1; ++i)
	{
		isOver = true;
		for(int j = 0; j < n - 1 - i; ++j)
		{
			if(arr[j] > arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				isOver = false;
			}
		}
		if(isOver)
			break;
	}

	display(arr, n);
}

//選擇排序
void choose_sort(int * arr, int n)
{
	if( NULL == arr ||n < 1)
		return;
	int max, index, temp;
	for(int i = 0; i < n; ++i)
	{
		max = arr[0];
		index = 0;
		for(int j = 0; j < n - i; ++j)
		{
			if(arr[j] > max)
			{
				index = j;
				max = arr[j];
			}
		}
		temp = arr[n - i - 1];
		arr[n - i - 1] = arr[index];
		arr[index] = temp;
	}

	display(arr, n);
}

//插入排序,與初始化次序有關
void insert_sort(int * arr, int n)
{
	if( NULL == arr ||n < 1)
		return;
	int temp;
	for(int i = 1; i < n; ++i)
	{
		temp = arr[i];
		int j;
		for(j = i - 1; j >= 0&& arr[j] > temp; --j)
		{
			arr[j + 1] = arr[j];
		}
		arr[j + 1] = temp;
	}
	display(arr, n);
}


//希爾排序
void  shell_sort(int *arr, int n)
{
	int d, i, j, temp;
	for(d = n/2; d >= 1; d = d/2)
	{
		for(i = d; i < n; ++i)
		{
			temp = arr[i];
			for(j = i - d; j >= 0&&arr[j] > temp; j = j - d)
			{
				arr[j + d] = arr[j];
			}
			arr[j + d] = temp;
		}
	}
	display(arr,n);
}


//歸併排序
void merge_sort(int * arr, int begin, int end, int * temp)
{
	if(begin < end)
	{
		int mid = (begin + end )/2;
		merge_sort(arr,begin,mid,temp);
		merge_sort(arr,mid + 1,end,temp);
		merge_array(arr,begin,mid,end,temp);
	}
}

//二路歸併左右有序的數組
void merge_array(int *arr,int begin, int mid, int end, int *temp)
{
	int i = begin, j = mid + 1, m = mid, n = end, k = 0;
	while(i <= m &&j <= n)
	{
		if(arr[i] <= arr[j])
		{
			temp[k++] = arr[i++];
		}
		else
		{
			temp[k++] = arr[j++];
		}
	}
	while(i < m)
		temp[k++] = arr[i++];
	while(j < n)
		temp[k++] = arr[j++];

	for(i = 0; i < k; ++i)
		arr[begin + i] = temp[i];
}


void MergeSort(int *arr, int n)  
{  
	int *p = new int[n];  
	if (NULL == p)  
		return;  
	merge_sort(arr, 0, n - 1, p);  
	display(arr,n);
	delete[] p;  
} 


//快速排序
void quick_sort(int *arr, int begin, int end)
{
	if(begin < end)
	{
		int i = begin, j = end;
		int temp = arr[i];
		while(i < j)
		{
			while(i < j&&arr[j--] > temp)
				;
			arr[i] = arr[j];

			while(i < j&&arr[++i] < temp)
				;
			arr[j] = arr[i];
		}
		arr[i] = temp;
		quick_sort(arr,begin,i - 1);
		quick_sort(arr,i +1,end);
	}

}
void QuickSort(int *arr, int n)
{
	quick_sort(arr, 0, n - 1);
	display(arr, n);
}

//顯示輸出數組
void display(int *arr, int n)
{
	//for(int i = 0; i < n; ++i)
	//{
	//	cout<<arr[i]<<"      ";
	//}
	cout<<endl;
}

//隨機產生1到n 的整數
long random(long n)
{
	return (long)(n*rand()/(RAND_MAX+1.0)) + 1; 
}

"test.cpp":

#include"sort_algorithms.h"

int main()
{
	int num = 100000;
	int * arr = new int[num];

	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);

	clock_t start,end;
	start=clock();
	cout<<"冒泡排序:"<<endl;
	bubble_sort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;


	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);

	start=clock();
	cout<<"選擇排序:"<<endl;
	choose_sort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;


	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);

	start=clock();
	cout<<"插入排序:"<<endl;
	insert_sort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;




	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);

	start=clock();
	cout<<"希爾排序:"<<endl;
	shell_sort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;

	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);


	start=clock();
	cout<<"歸併排序:"<<endl;
	MergeSort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;


	for(int i = 0; i < num; ++i)
		arr[i] = random(10*num);


	start=clock();
	cout<<"快速排序:"<<endl;
	QuickSort(arr,num);
	end=clock();
	cout<<num<<"個數排序花了: "<<end - start<<" 毫秒"<<endl;
	cout<<"======================================================"<<endl;


	delete arr;
	return 0;
}

以下兩次運行隨機產生100000個1-1000000的整數的排序結果:



下面是運行第二次的結果:



針對希爾排序、歸併排序、快速排序,我還運行了一次隨機產生一億個一到十億間的數字進行排序,其他3個排序效率太低,運行時間太長,所以註釋掉了,結果如下:



從以上的結果可以看出,從時間角度看,快速排序確實是評價最優的。時間複雜度爲0(n*n)在處理大量數據的排序中確實很難滿足需求,時間成本太高。下面給出一個在百度百科上找到的總結性的圖表:



關於堆排序和基礎排序尚未給出具體實現的代碼,日後有時間再行補充。

寫此博客,重在與大家分享,共同學習,相互提高,如有疑問或建議,請留言。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章