数据结构与算法第九节:排序算法之冒泡、插入和选择排序源代码解析

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;

}

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