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;
}