數據結構與算法第九節:排序算法之冒泡、插入和選擇排序源代碼解析

1. 常用經典排序算法

冒泡排序、插入排序、選擇排序; O(n^2)

快速排序、歸併排序`; O(nlogn)

計數排序、基數排序、桶排序; O(n)

2. 冒泡排序

(1). 只會操作相鄰的兩個數據;
在這裏插入圖片描述

  • 源代碼案例
	void bubbleSort(int* a, int n)   // 冒泡排序
	{
		if(n<=1) return;
		
		for(int i=0; i<n; i++)
		{
			bool flag = false;
			for(int j=0; j<n-i-1;j++)
			{
				/************ 
				 * 冒泡排序說明: 空間複雜度爲O(1)(原地排序), 最好的時間複雜度爲O(n), 最壞時間複雜度爲O(n^2), 平均時間複雜度O(n^2)
				 * 1.j是從0開始遍歷數組的,因爲每一次冒泡之後,大數會被移到最末尾;
				 * 2.每一次排序之後, 下一次j的遍歷將會減少一位;
				 * 3.對於相同的數字位置不會移動,所以該算法是穩定排序;
				 * 
				 * ******/
				if(a[j] >a[j+1])
				{
					//std::swap(a[j], a[j+1]);
					int tmp = a[j];
					a[j] = a[j+1];
					a[j+1] = tmp;
					flag = true;
				}
			}
			if(!flag) break;
		}
	}

3. 插入排序

Q1: 一個有序的數組,往裏添加一個新的數據後,如何繼續保持數據有序?
A1: 只需要遍歷數據,找到數據應該插入的位置將其插入即可;
在這裏插入圖片描述

插入排序: (元素比較+移動)

(1). 將數組分爲已排序區間和未排序區間,初始已排區間只有一個元素;

(2). 然後將未排序區間中的元素,在已排序區間中找到合適的插入位置將其插入,並保證已排序區間數據一直有序;

(3). 重複這個過程, 直到未排序區間中元素爲空,算法結束;

  • 源代碼案例
	void insertSort(int* a, int n)  // 插入排序
	{
		if(n < 1) {return;}
		
		for(int i=1; i<n; i++)
		{
			int value = a[i];
			int j=i-1;
			for(; j>=0; j--)
			{
				if(a[j] > value)
				{
					a[j+1] = a[j];   
					/***********
					 * 插入排序說明:  空間複雜度爲O(1), 最好時間複雜度爲O(n), 最壞時間度爲O(n^2), 平均時間複雜度爲O(n^2)
					 * 
					 * 	1. i從序號1開始往後遍歷, j從i-1的位置往後遍歷判斷i之前是否有比i大的數字;
					 * 	2. 當i之前的數字有比i當前的數字大, 也就是a[j]>value;
					 * 	3. 將前一位置的數值賦值給當前當前位置(value直到最後纔會發生改變); a[j+1] = a[j]; 
					 * 	4. 完成之後, 將value值賦給最後的a[j], 但是最後在完成循環之後, j--了一次,所以最後應該賦值給a[j+1];
					 ***************************************/
				}
				else
				{
					break;
				}
			}
			cout<<"j = "<<j<<", ";
			a[j+1] = value;
		}
	}

4. 選擇排序

選擇排序的思路類似插入排序
(1). 將其分爲已排序區間和未排序區間;
(2). 選擇排序每次會從未排序區間中找到最小元素, 將其放到已排序區間的末尾;
在這裏插入圖片描述

  • 源代碼案例
void selectSort(int* a, int n)  // 選擇排序
	{
		if(n<1) return;
		
		for(int i=0; i<n; i++)
		{
			int minId = select_findMin(a, i, n);
			if(minId != i) // 這裏相同的值可能有不同的序號, 所以會導致相同的值出現交換, 即該算法不穩定。
			{
				std::swap(a[i], a[minId]);
				/**********************
				 * 選擇排序說明:  空間複雜度爲O(1), 最好/最壞/平均時間複雜度爲O(n^2), 
				 * 
				 * 	1. 多寫一個函數找出數組中的最小值;select_findMin();
				 * 
				 * 	2. 然後交換數組的初始值與這個最小值(不相等的話交換,相等則退出);
				 * 
				 * ********************************************************/
			}
		}
	}
	
	int select_findMin(int* a, int s, int n)
	{
		if(s == n-1) return s;
		int value = a[s];
		int id = s;
		for(int i=s; i<n; i++)
		{
			if(a[i+1] < value)
			{
				value = a[i+1];
				id = i+1;
			}
		}
		cout<<value<<","<<"\n";
		return id;
	}

5. 給出完整的代碼測試框架

在這裏插入圖片描述


#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;


class solutions
{
public: 
	
	void bubbleSort(int* a, int n)   // 冒泡排序
	{
		if(n<=1) return;
		
		for(int i=0; i<n; i++)
		{
			bool flag = false;
			for(int j=0; j<n-i-1;j++)
			{
				/************ 
				 * 冒泡排序說明: 空間複雜度爲O(1)(原地排序), 最好的時間複雜度爲O(n), 最壞時間複雜度爲O(n^2), 平均時間複雜度O(n^2)
				 * 1.j是從0開始遍歷數組的,因爲每一次冒泡之後,大數會被移到最末尾;
				 * 2.每一次排序之後, 下一次j的遍歷將會減少一位;
				 * 3.對於相同的數字位置不會移動,所以該算法是穩定排序;
				 * 
				 * ******/
				if(a[j] >a[j+1])
				{
					//std::swap(a[j], a[j+1]);
					int tmp = a[j];
					a[j] = a[j+1];
					a[j+1] = tmp;
					flag = true;
				}
			}
			if(!flag) break;
		}
	}
	
	
	void insertSort(int* a, int n)  // 插入排序
	{
		if(n < 1) {return;}
		
		for(int i=1; i<n; i++)
		{
			int value = a[i];
			int j=i-1;
			for(; j>=0; j--)
			{
				if(a[j] > value)
				{
					a[j+1] = a[j];   
					/***********
					 * 插入排序說明:  空間複雜度爲O(1), 最好時間複雜度爲O(n), 最壞時間度爲O(n^2), 平均時間複雜度爲O(n^2)
					 * 
					 * 	1. i從序號1開始往後遍歷, j從i-1的位置往後遍歷判斷i之前是否有比i大的數字;
					 * 	2. 當i之前的數字有比i當前的數字大, 也就是a[j]>value;
					 * 	3. 將前一位置的數值賦值給當前當前位置(value直到最後纔會發生改變); a[j+1] = a[j]; 
					 * 	4. 完成之後, 將value值賦給最後的a[j], 但是最後在完成循環之後, j--了一次,所以最後應該賦值給a[j+1];
					 ***************************************/
				}
				else
				{
					break;
				}
			}
			cout<<"j = "<<j<<", ";
			a[j+1] = value;
		}
	}

	void selectSort(int* a, int n)  // 選擇排序
	{
		if(n<1) return;
		
		for(int i=0; i<n; i++)
		{
			int minId = select_findMin(a, i, n);
			if(minId != i) // 這裏相同的值可能有不同的序號, 所以會導致相同的值出現交換, 即該算法不穩定。
			{
				std::swap(a[i], a[minId]);
				/**********************
				 * 選擇排序說明:  空間複雜度爲O(1), 最好/最壞/平均時間複雜度爲O(n^2), 
				 * 
				 * 	1. 多寫一個函數找出數組中的最小值;select_findMin();
				 * 
				 * 	2. 然後交換數組的初始值與這個最小值(不相等的話交換,相等則退出);
				 * 
				 *  
				 * ********************************************************/
			}
		}
	}
	
	int select_findMin(int* a, int s, int n)
	{
		if(s == n-1) return s;
		int value = a[s];
		int id = s;
		for(int i=s; i<n; i++)
		{
			if(a[i+1] < value)
			{
				value = a[i+1];
				id = i+1;
			}
		}
		cout<<value<<","<<"\n";
		return id;
	}
};

int main()
{
	int a[6] = {4,5,6,1,3,2};
	
	std::cout<<"Before Sort Data: "<<std::endl;
	for(int i =0; i<6; i++)
	{
		cout<<a[i]<<",";
	}
	cout<<endl;
	
	solutions solve;
	//solve.insertSort(a, 6);
	//solve.selectSort(a,6);
	
	solve.bubbleSort(a,6);
	
	std::cout<<"After Sort Data: "<<std::endl;
	for(int i =0; i<6; i++)
	{
		cout<<a[i]<<",";
	}
	cout<<endl;

}

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