1. 程式人生 > >【C++】各種排序執行時間的測試

【C++】各種排序執行時間的測試

我們經常見的就是對一組資料進行排序,而排序的方法有很多種。

常見的排序方法有:

氣泡排序,插入排序,希爾排序,快速排序,堆排序,選擇排序,歸併排序,計數排序,基數排序。

這些常見的排序方法,對同一組資料進行排序的時候有塊也又慢,它們的時間複雜度也不一樣:


接下來我們就來簡單的測試一下執行這些排序方法所需要的時間。

首先,計算一個程式執行的時間的函式是clock'函式,它放在time,h裡面。

我們在開始執行程式的時候定義start,執行完程式的時候定義一個finish,兩個時間相減,則可以得到該程式執行的時間 。

程式碼實現:

test.h檔案

#pragma once   
#include <iostream>
using namespace std;
#include <time.h>
#include<assert.h>
#include<stack>
#define M 100 /* 執行次數 */
#define N 500 /* 陣列大小 */

void Menu();//選單函式
void BubbleSort(int *a, size_t n);//1,氣泡排序
void InsertSort(int *a, size_t n);//2,插入排序
void SheelSort(int *a, size_t n);//3,希爾排序
void SelectSort(int *a, size_t n);//4,選擇排序
void QuickSort(int *a, size_t left, size_t right);//5,快速排序演算法
void HeapSort(int *a, size_t n);//6,堆排序
void MergeSort(int* a, size_t n);//7,歸併排序
void CountSort(int *a, size_t n);//8,計數排序
void LSDSort(int *a, size_t n);//9,基數排序

test.cpp檔案

#include"test.h"

void Menu()
{
	cout << "**********************************************\n";
	cout << "*****************1,氣泡排序******************\n";
	cout << "*****************2,插入排序******************\n";
	cout << "*****************3,希爾排序******************\n";
	cout << "*****************4,選擇排序******************\n";
	cout << "***************5,快速排序演算法****************\n";
	cout << "*****************6,堆排序********************\n";
	cout << "*****************7,歸併排序******************\n";
	cout << "*****************8,計數排序******************\n";
	cout << "*****************9,基數排序******************\n";
	cout << "*******************0,退出********************\n";
	cout << "**********************************************\n";
	cout << "請選擇一種排序的演算法: " << endl;
}
//1,氣泡排序
void BubbleSort(int *a, size_t n)
{
	int i, j;
	int tmp;
	for (i = 1; i < n; i++)
	{
		for (j = n-1; j >= i; j--)
		{
			if (a[j + 1] < a[j])
			{
				tmp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = tmp;
			}
		}
	}
}

//2,插入排序
void InsertSort(int *a, size_t n)
{
	int i;
	int j;
	for (i = 2; i <= n; i++)
	{
		a[0] = a[i];
		j = i - 1;
		while (a[0] < a[j])
		{
			a[j + 1] = a[j];
			j--;
		}
		a[j + 1] = a[0];
	}
}

//3,希爾排序
void SheelSort(int *a, size_t n)
{
	assert(a);
	int gub = n / 2;//先定義增量為n/2
	while (gub > 0)
	{
		for (size_t i = gub; i < n; ++i)//從第gub個數據處開始進行交換
		{
			int tmp = a[i];
			int end = i - gub;
			while (end >= 0 && tmp < a[end])
			{
				a[end + gub] = a[end];
				end = end - gub;
			}
			a[end + gub] = tmp;
		}
		gub /= 2;
	}
}

//4,選擇排序
void SelectSort(int *a, size_t n)
{
	assert(a);
	int left = 0;
	int right = n - 1;
	while (left < right)
	{
		size_t MinIndex = left;
		size_t MaxIndex = right;
		for (size_t i = left; i <= right; ++i)
		{
			if (a[i] < a[MinIndex])
			{
				MinIndex = i;
			}
			if (a[i] > a[MaxIndex])
			{
				MaxIndex = i;
			}

		}
		swap(a[left], a[MinIndex]);
		if (MaxIndex == left)
		{
			MaxIndex = MinIndex;
		}
		swap(a[right], a[MaxIndex]);
		++left;
		--right;
	}
}

//5,快速排序演算法
int PartSort(int *a, size_t left, size_t right)

{
	int i, j;
	static int w = 0;
	int temp;
	i = left;
	j = right;
	temp = a[i];
	do
	{
		while ((a[j]>temp) && (i<j))
		{
			j--;
			w++;
		}
		if (i<j)
		{
			a[i] = a[j];
			i++;
			w++;
		}
		while ((a[i]<= temp) && (i<j))
		{
			i++;
			w++;
		}
		if (i<j)
		{
			a[j] = a[i];
			j--;
			w++;
		}
	} while (i != j);
	a[i] = temp;
	return i;
}

void QuickSort(int *a, size_t left, size_t right)
{
	assert(a);
	if (left >= right)
	{
		return;
	}
	int div = PartSort(a, left, right);
	QuickSort(a, left, div - 1);
	QuickSort(a, div + 1, right);
}

//6,堆排序
void AdjustDown(int *a, size_t n, int root)
{
	size_t parent = root;
	size_t child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			++child;
		}
		if (a[child] > a[parent])
		{
			swap(a[child], a[parent]);
			parent = child;;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int *a, size_t n)
{
	assert(a);
	int parent = (n - 2) >> 1;
	//建堆
	for (; parent >= 0; --parent)
	{
		AdjustDown(a, n, parent);
	}
	for (int i = n - 1; i >= 0; --i)
	{
		swap(a[0], a[i]);
		AdjustDown(a, i, 0);
	}
}

//7,歸併排序
void _MergeSort(int* src, int* dst, int left, int right)
{
	if (left >= right)
		return;
	int mid = left + (right - left) / 2;
	//[left,mid],[mid+1,right]
	_MergeSort(src, dst, left, mid);
	_MergeSort(src, dst, mid + 1, right);

	int begin1 = left; int begin2 = mid + 1;
	int index = 0;

	while (begin1 <= mid && begin2 <= right)
	{
		if (src[begin1] < src[begin2])
			dst[index++] = src[begin1++];
		else
			dst[index++] = src[begin2++];
	}

	while (begin1 <= mid)
		dst[index++] = src[begin1++];
	while (begin2 < right)
		dst[index++] = src[begin2++];

	int i = 0; int j = left;
	while (i < index)
		src[j++] = dst[i++];
}
void MergeSort(int* arr, size_t len)
{
	assert(arr);
	assert(len > 0);
	int *tmp = new int[len];
	_MergeSort(arr, tmp, 0, len - 1);
}

//8,計數排序
void CountSort(int *a, size_t n)
{
	int i, j, k;
	int C[N + 1] = { 0 };  /*用於計數的C陣列的所有元素初值為0*/
	for (i = 0; i<n; i++)
		C[a[i]]++;    /*例如,R[i].key為6時,C[6]++,C[R[i].key]是R[i].key出現的次數*/
	k = 0;
	for (j = 0; j <= N; j++)    /*考察每一個j*/
	for (i = 1; i <= C[j]; i++)   /*j=R[j].key出現過C[j]個,此即是排序的結果*/
		a[k++] = j;
}

//9,基數排序
size_t GetMaxDigit(int *a, size_t n)
{
	size_t digit = 1;
	size_t base = 10;
	for (size_t i = 0; i < n; i++)
	{
		while (a[i] >= base)
		{
			base *= 10;
			digit++;
		}
	}
	return digit;
}
void LSDSort(int *a, size_t n)
{
	size_t maxDigit = GetMaxDigit(a, n);
	size_t base = 1;

	size_t *bucket = new size_t[n];
	while ((maxDigit--) > 0)
	{
		size_t counts[10] = { 0 };
		size_t start[10] = { 0 };
		start[0] = 0;

		for (size_t i = 0; i < n; i++)
		{
			size_t num = (a[i] / base) % 10;
			counts[num]++;
		}
		for (size_t i = 1; i < 10; i++)
		{
			start[i] = start[i - 1] + counts[i - 1];
		}

		for (size_t i = 0; i < n; i++)
		{
			size_t num = (a[i] / base) % 10;
			bucket[start[num]++] = a[i];
		}
		memcpy(a, bucket, sizeof(size_t)*n);
		base *= 10;
	}
}

main.cpp

#include"test.h"
void main() 
{
	int a[N], i, j, p;
	Menu();
	do{
		cin >> p;
		double start, finish; /* 定義開始的時間和結束的時間 */
		start = (double)clock(); 
		for (j = 0; j<M; j++) 
		{ /* 執行M次 */
			for (i = 0; i<N; *(a + i++) = rand() % 10); /* 每次對陣列進行重新賦值 */
			switch (p)
			{
			case 1:BubbleSort(a, N); 
				break;
			case 2:InsertSort(a, N);
				break;
			case 3:SheelSort(a, N);
					break;
			case 4:SelectSort(a, N);
					break;
			case 5:QuickSort(a, 0, N - 1);
					break;
			case 6:HeapSort(a, N);
					break;
			case 7:MergeSort(a, N);
				break;
			case 8:CountSort(a, N);
					break;
			case 9:LSDSort(a, N);
			case 0:break;
			default:break;
			}
		}
		finish = (double)clock();
		printf("%.4fms\n", (finish - start));
	} while (p != 0);
}
在本個小測試中,一共測試了九個排序方法:氣泡排序,插入排序,希爾排序,選擇排序,快速排序,堆排序,歸併排序,計數排序,基數排序。

接下來我們來看一下測試的結果:


由執行的結果可以得出結論:


由這個簡單的小測試,我們可以知道,排序中最快的是計數排序,然後是基數排序,氣泡排序是執行時間最長的一個方法。

這只是一個簡單的小測試,還有不完善的地方,望多多指教!

相關推薦

C++各種排序執行時間測試

我們經常見的就是對一組資料進行排序,而排序的方法有很多種。 常見的排序方法有: 氣泡排序,插入排序,希爾排序,快速排序,堆排序,選擇排序,歸併排序,計數排序,基數排序。 這些常見的排序方法,對同一組資料進行排序的時候有塊也又慢,它們的時間複雜度也不一樣: 接下來我們就來簡

初賽各種排序演算法總結

一、演算法評價 排序方法 平均時間 最好時間 最壞時間 氣泡排序(穩定) O(n^2) O(n) O(n^2) 選擇排序(

C++併發-1 執行緒管理-1

【建立】 有四種方式:  預設 傳入執行函式 定義一個類, 過載 operator() ,執行緒執行過程 lambda // std::thread 簡單使用 namespace T1 { template<class T> class Thread

C#氣泡排序、隱式和顯式轉換、函式及異常處理

一、普通氣泡排序: C#中常見的排序方法有:氣泡排序,快速排序,插入排序,選擇排序、堆排序以及歸併排序。雖然還沒學習過,但是也有耳聞,就先把它們先歸類。今天主要講這裡面最常見的氣泡排序。 【概念】 氣泡排序也就是講一組需要排序的數,進行從小到大,或從大到小的排列。計算機

OpenCV測算程式碼執行時間

OpenCV 有一個非常實用的函式可以用來測算函式或程式碼段的執行時間,它就是 cv::get TickCount() , 該函式會返回從最近一次計算機開機到當前的時鐘週期數。 在程式碼開始和結 束時記錄這個時鐘週期數,就可以計算程式碼的執行時間。 若想得到以秒為單位的程

opencv獲取程式執行時間

double t = (double)getTickCount(); // do something ...返回該處程式碼執行所耗的時間,單位為秒 t = ((double)getTickCount(

C# 陣列排序和取值練習

1.從鍵盤接收一行用逗號分隔的5個整數,儲存至有5個元素的陣列中。 2.分別輸出正序和逆序的結果。 3/輸出陣列最大值和平均值,平均值保留1位小數。 4.存在非法輸入時顯示提示訊息並可重新輸入資料。 5.按下回車鍵退出,任意鍵繼續輸入。 輸出結果如圖所示。 -------

C++C++中幾種測試程式執行時間的方法

關於C++中計算時間的一些總結 一、使用GetTickCount()函式 GetTickCount()是一個函式,可以把它理解為打點計時器。GetTickCount()是通過計算從函式開始執行計時

C++測試時間

為了精準的獲取程式塊的執行時間,使用sys/time.h進行時間測試。 struct timeval start; struct timeval end; unsigned long Time = 0;

C#datetimepicker裡面如何設定日期為當天日期,而時間設為0:00或23:59?

今天無意中發現要根據日期查詢時間,datatimepicker控制元件會把時間預設成當前時間(當你的控制元件只顯示日期時),這樣查詢出來的出來的資料會有誤差,用來下面的辦法成功設定日期為當天日期,而時間設為0:00或23:59。 1 2 3 4 5 6 /

C#C#執行緒_I/O限制的非同步操作

目錄結構: contents structure [+] 為什麼需要非同步IO操作 C#的非同步函式 async和await的使用 非同步函式的狀態機 非同步函式如何轉化為狀態機 如何擴充套件非

C#獲取日期時間

前言 我們在機房重構的時候,我們經常會用到獲取時間和日期的操作! 我們可以通過使用DataTime這個類來獲取當前的時間。通過呼叫類中的各種方法我們可以獲取不同的時間:如:日期(2008-09-04)、時間(12:12:12)、日期+時間(2008-09-04 12:11:10)等。 時

初探“ 選擇排序 ” ——C++程式碼實現

  選擇排序(Selection sort)是一種簡單直觀的排序演算法。無論什麼資料進去都是 O(n²) 的時間複雜度。所以用到它的時候,資料規模越小越好。唯一的好處可能就是不佔用額外的記憶體空間了吧。   簡單排序處理流程 首先在未排序序列中找到最小

Cmain (int argc,char *argv[]) 或main (int argc,char **argv)後臺(CMD下)執行說明

文章目錄 main (int argc,char *argv[]) 或main (int argc,char **argv)後臺(CMD下)執行說明 說明 一、main (int argc,char *argv[]) 或mai

C++編譯、連結、執行原理+強弱符號

【C++】編譯、連結、執行原理+強弱符號 虛擬地址空間 作用:程序地址空間需要隔離,防止惡意的程式修改其他程式的記憶體資料,所以計算機需要虛擬地址空間 其中: .data:已經初始化,並且初始化不為0的資料。 .bss:未初始化,或者初始化為0的資料。 例如: #i

C#C#執行緒_混合執行緒的同步構造

目錄結構: contents structure [+] 一個簡單的混合鎖 FCL中的混合鎖 ManualResetEventSlim類和SemaphoreSlim類 Monitor類和同步塊 ReaderWriterLockSlim類

C#List多權重排序

List.Sort((x, y) => -x.CompareTo(y));  倒序排序 List.Sort((x, y) => x.CompareTo(y));  正序排序   如果需要比較多個條件,比如裝備排序:橙>紫>藍,品質越高

C#xUnitMoq.NET單元測試Mock框架Moq初探!

在TDD開發模型中,經常是在編碼的同時進行單元測試的編寫,由於現代軟體開發不可能是一個人完成的工作,所以在定義好介面的時候我們就可以進行自己功能的開發(介面不能經常變更),而我們呼叫他人的功能時只需要使用介面即可。 但我們在編寫自己的單元測試並進行功能驗證的時候,如果介面的實現人還沒有完成程式碼怎麼

java各種Map中keySet()返回值的排序問題

上回說到,由於對資料進行處理的時候是按照亂序一行一行的處理,導致並行執行緒各自佔據了一部分資料,誰也不肯釋放,從而發生死鎖。 為什麼會亂序,是因為取得資料行主鍵的時候,使用了HashMap.keySet()方法,而這個方法返回的Set結果,裡面的資料是亂序排放的。 Jav

leetcode排序陣列中刪除重複項(C、Python解答)

題目: 給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。 不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。 示例 1: 給定陣列 nums = [1,1,2], 函式應該