算法與數據結構(2): 插入排序

在這裏插入圖片描述

注:轉載請標明原文出處鏈接:https://xiongyiming.blog.csdn.net/article/details/100552609


1 插入排序

插入排序(Insertion sort)是一種簡單直觀且穩定的排序算法。如果有一個已經有序的數據序列,要求在這個已經排好的數據序列中插入一個數,但要求插入後此數據序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,算法適用於少量數據的排序,時間複雜度爲O(n^2)。是穩定的排序方法。插入算法把要排序的數組分成兩部分:第一部分包含了這個數組的所有元素,但將最後一個元素除外(讓數組多一個空間纔有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。
插入排序的基本思想是:每步將一個待排序的記錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完爲止。
(以上均來自百度百科)

在這裏插入圖片描述


下面舉個例子來說明插入排序,按照從小到大排序

在這裏插入圖片描述
對於第一個元素8保持不動

在這裏插入圖片描述

上圖中,因爲第二個元素6<8,則需要調換順序,如下圖所示:

在這裏插入圖片描述

在這裏插入圖片描述

下面再看第3個因素2,與左邊最近的元素相比較,2<8,則需要調換位置。

在這裏插入圖片描述

調換元素位置後,如下圖所示:

在這裏插入圖片描述

同樣的道理,2<6,則需要調換位置。調換元素位置後,如下圖所示:

在這裏插入圖片描述
與上面類似,一直到所有元素從小到大排序。



2 實現簡單的插入排序

代碼示例


#include<iostream>

using namespace std;

template<typename T>

//使用插入排序 讓數組中的數字從小到大排序 //
void insertionSort(T arr[],int n) {
	for(int i=1; i<n; i++) //i=1,對於插入排序,第0個元素不用考慮

		//尋找元素arr[i]合適的插入位置
		for (int j = i; j > 0; j--) {
			if (arr[j] < arr[j - 1])
				swap(arr[j], arr[j - 1]);
			else
				break;
		}

}


int main() {
	int a[10] = { 10,9,8,7,6,5,4,3,2,1 };
	insertionSort(a, 10);
	for (int i = 0; i < 10; i++)
		cout << a[i] << " ";
	cout << endl;
	

	cin.get();
	return 0;
}

運行結果

在這裏插入圖片描述



3 測試排序算法的性能

插入排序和選擇排序性能對比

selectionSort.h

#pragma once
#include<iostream>
using namespace std;

template<typename T>

//使用選擇排序 讓數組中的數字從小到大排序 //
void selectionSort(T arr[], int n) {
	for (int i = 0; i < n; i++) {

		//尋找[i,n)區間內的最小值
		int minIndex = i;
		for (int j = i + 1; j < n; j++) {
			if (arr[j] < arr[minIndex])
				minIndex = j;
			swap(arr[i], arr[minIndex]); //交換函數
		}
	}
}

SortTestHelp,h

#pragma once
#include<iostream>
#include<string>
#include<ctime>
#include<cassert>

using namespace std;

namespace SortTestHelp {

	// 生成有n個元素的隨機數組,每個元素的隨機範圍爲[rangeL,rangeR] //
	int *generateRandomArray(int n, int rangeL, int rangeR) {

		assert(rangeL <= 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;
			else
				return true;
		}
			
		return true;
	}


	//計算時間函數模板
	template<typename T>

	void testSort(string sortName, void(*sort)(T[],int),T arr[],int n) {
		
		clock_t startTime = clock();
		sort(arr, n);
		clock_t endTime = clock();


		assert(isSorted(arr, n)); //assert()作用是如果它的條件返回錯誤,則終止程序執行
		cout << sortName << " :" << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;

		return;
	}

	//複製數組
	int *copyIntArray(int a[], int n) {
		int *arr = new int[n];
		copy(a, a + n, arr);
		return arr;
	}


}

main.cpp

#include<iostream>
#include"SortTestHelp.h"
#include"selectionSort.h"
using namespace std;

template<typename T>

//使用插入排序 讓數組中的數字從小到大排序 //
void insertionSort(T arr[],int n) {
	for(int i=1; i<n; i++) //i=1,對於插入排序,第0個元素不用考慮

		//尋找元素arr[i]合適的插入位置
		for (int j = i; j > 0; j--) {
			if (arr[j] < arr[j - 1])
				swap(arr[j], arr[j - 1]);
			else
				break;
		}

}


int main() {
	int n = 10000;

	int *arr = SortTestHelp::generateRandomArray(n, 0, n);
	int *arr2 = SortTestHelp::copyIntArray(arr, n);


	SortTestHelp::testSort("SelctionSort", selectionSort<int>, arr, n);
	SortTestHelp::testSort("InsertionSort", selectionSort<int>, arr2, n);


	delete[] arr;
	delete[] arr2;

	cin.get();
	return 0;
}

運行結果

在這裏插入圖片描述

:對於接近有序數組,插入排序的素對較快




參考資料

[1] 算法與數據結構–綜合提升篇(c++版)

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