資料結構與演算法C++之插入排序
阿新 • • 發佈:2018-11-14
本篇實現的是插入排序,其演算法複雜度是O(n2),插入排序的原理來自部落格:
插入排序原理很簡單,將一組資料分成兩組,分別將其稱為有序組與待插入組。左邊為有序組,右邊為待插入組,每次從待插入組中取出一個元素,與有序組的元素進行比較,並找到合適的位置,將該元素插到有序組當中。就這樣,每次插入一個元素,有序組增加,待插入組減少。直到待插入組元素個數為0。當然,插入過程中涉及到了元素的移動。為了排序方便,一般將資料第一個元素視為有序組,其他均為待插入組。然後有序組元素慢慢增加,待插入組元素慢慢減少,原理圖如下
下面是C++實現:
#include <iostream>
using namespace std;
template<typename T>
void InsertionSorting(T arr[], int n){
for (int i = 0; i < n - 1; i++){
for (int j = i + 1; j > 0; j--){
if (arr[j-1] > arr[j]){
swap(arr[j-1], arr[j]);
}
else
break;
}
}
return ;
}
int main(){
int a[] = {10,9,8,7,6,5,4,3,2,1,0};
int n = 11;
InsertionSorting(a, n);
for(int i = 0; i < n; i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
輸出結果為:
上面只是簡單的實現了11個元素排序,下面我們編寫一個含有自動生成陣列的函式、列印輸出函式、複製陣列函式、測試排序函式正確性、計時的標頭檔案SortingHelp.h,來測試插入排序演算法和 上一篇的選擇排序演算法:
//SortingHelp.h
#include <iostream>
#include <ctime> //time()函式
#include <cstdlib> //rand()函式
#include <cassert> //assert()函式
using namespace std;
int* generateRandomArray(int n, int rangeL, int rangeR){//生成隨機陣列
assert(rangeL < rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++){
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
}
return arr;
}
template<typename T>
void printArray(T arr[], int n){//列印陣列元素
for (int i = 0; i < n; i ++){
cout<<arr[i]<<" ";
}
cout<<endl; //換行
return;
}
template<typename T>
bool isSorted(T arr[], int n){//測試排序演算法是否正確
for (int i = 0; i < n - 1; i++){
if (arr[i] > arr[i + 1])
return false;
}
return true;
}
template<typename T>
void testSorting(string sortName, void(*sorting)(T[], int), T arr[], int n){//第二個引數是傳入排序函式的指標
clock_t startClock = clock();
sorting(arr, n);
clock_t endClock = clock();
assert(isSorted(arr, n));
cout<<sortName<<" : "<<double(endClock-startClock)/CLOCKS_PER_SEC<<" s"<<endl;
return;
}
int* copyIntArray(int arr[], int n){
int* arr2 = new int[n];
copy(arr, arr+n, arr2);
return arr2;
}
template<typename T> //定義模板型別,使對各種資料型別都適用,如double,float,string
void SelectionSorting(T a[], int n){//選擇排序演算法
for (int i = 0; i < n; i++){
int minIndex = i;
for (int j = i + 1; j < n; j++){
if (a[j] < a[minIndex])
minIndex = j;
}
swap(a[i], a[minIndex]);
}
}
測試程式為:
#include <iostream>
#include "SortingHelp.h"
using namespace std;
template<typename T>
void InsertionSorting(T arr[], int n){
for (int i = 0; i < n - 1; i++){
for (int j = i + 1; j > 0; j--){
if (arr[j-1] > arr[j]){
swap(arr[j-1], arr[j]);
}
else
break;
}
}
return;
}
int main()
{
int n = 10000;
int *arr = generateRandomArray(n, 0, n);
int *arr2 = copyIntArray(arr, n);
testSorting("SelectionSorting", SelectionSorting, arr, n);
testSorting("InsertionSorting", InsertionSorting, arr2, n);
delete[] arr;//最後刪除陣列開闢的空間
delete[] arr2;
return 0;
}
輸出為
因為在插入排序中用了交換swap操作,每次swap需要三次賦值,而每次移動操作只需要一次賦值,所以插入操作的執行時間比選擇排序長一些。