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