1、冒泡排序
/* 排序算法-1
名称:冒泡排序
原理:
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
算法复杂度:
最好:O(n)
最坏:O(n^2)
稳定性:
稳定排序
*/
#include<iostream>
using namespace std;
void Bubble_Sort(int a[], int n) { //普通版本
for (int i = 0; i < n - 1; i++)
for (int j = n - 1; j > i; j--)
if (a[j-1] > a[j]) swap(a[j], a[i]);
}
void Impove_Bubble_Sort(int a[], int n) { //优化后的,当排序好了之后就不需要在遍历了
int flag = 0;
for (int i = 0; i < n - 1; i++) {
flag = 0;
for (int j = n - 1; j > i; j--) {
if (a[j-1] > a[j]) {
swap(a[j-1], a[j]);
flag = 1;
}
}
if (!flag) break;
}
}
void Recursive_Bubble_Sort(int a[], int n, int size) { //递归版本
if (n == size-1) return;
for (int i = size - 1; i > n; i--)
if (a[i - 1] > a[i]) swap(a[i - 1], a[i]);
Recursive_Bubble_Sort(a, n + 1, size);
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
// Bubble_Sort(num, N);
// Impove_Bubble_Sort(num, N);
Recursive_Bubble_Sort(num, 0, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
/* 排序算法-2
名称:选择排序
原理:
它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,
存放在序列的起始位置,直到全部待排序的数据元素排完
算法复杂度:
最好:O(n)
最坏:O(n^2)
(交换次数用少,比冒泡排序快点)
稳定性:
不稳定
*/
#include<iostream>
using namespace std;
void Selection_Sort(int a[], int n) {
int sentry;
for (int i = 0; i < n - 1; i++) {
sentry = i; //设置最小值的哨兵
for (int j = i + 1; j < n; j++) {
if (a[j] < a[sentry]) sentry = j;
}
swap(a[sentry], a[i]); //交换第一个和后面找出的最小值
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
Selection_Sort(num, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
/* 排序算法-3
名称:插入排序
原理:
第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),
而第二部分就只包含这一个元素(即待插入元素)。
在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中
算法复杂度:
最好:O(n)
最坏:O(n^2)
稳定性:
不稳定
*/
#include<iostream>
using namespace std;
void Insertion_Sort(int a[], int n) {
int j, key; //表示哨兵
for (int i = 1; i < n; i++) {
key = a[i];
for (j = i - 1; j >= 0 && a[j] > key; j--)
a[j+1] = a[j];
a[j+1] = key;
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
Insertion_Sort(num, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
4、希尔排序
/* 排序算法-4
名称:希尔排序
方法:
1、插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
2、但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。
所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;
然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),
即所有记录放在同一组中进行直接插入排序为止。
算法复杂度:
最好:O(n)
最坏:O(nlog2n)
稳定性:
稳定
*/
#include<iostream>
using namespace std;
void Shell_Sort(int a[], int n) {
int j, sentry;//哨兵
for (int increment = n / 2; increment > 0; increment /= 2) { //增量取值最后一个一定要等于1
for (int i = increment; i < n; i++) {
sentry = a[i]; //设置哨兵
for (j = i; j > 0 && sentry < a[j - increment]; j -= increment) {
if (j - increment >= 0)
swap(a[j], a[j - increment]);
}
}
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
// cout << N;
Shell_Sort(num, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
5、堆排序
/* 排序算法-4
名称:堆排序
方法:
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
算法复杂度:
平均性能:O(N*logN)
稳定性:
不稳定
*/
#include<iostream>
using namespace std;
void HeapAdjust(int a[], int s, int n) { //此函数要实现使每个父亲结点都大于其子节点
int temp = a[s]; //保存当前父亲结点
for (int i = 2 * s; i < n; i *= 2) { //从保存父节点的第一个左边子节点开始查找
if (i < n-1 && a[i] < a[i+1]) i++;
if (temp >= a[i]) break; //测试的时候少了一个等于号,导致结果输入不出来。原因是数据是从0开始的
a[s] = a[i];
s = i;
}
a[s] = temp;
}
void Heap_Sort(int a[], int n) {
for (int i = n/2 - 1; i >= 0; i--) { //二叉树的性质,从一半开始找就行
HeapAdjust(a, i, n); //构建好一个堆
}
for (int i = n - 1; i > 0; i--) {
swap(a[0], a[i]);
HeapAdjust(a, 0, i);
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
// cout << N;
Heap_Sort(num, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
6、归并排序
/* 排序算法-4
名称:归并排序
方法:
归并排序具体工作原理如下(假设序列共有n个元素):
将序列每相邻两个数字进行归并操作(merge),形成floor(n/2)个序列,排序后每个序列包含两个元素
将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
重复步骤2,直到所有元素排序完毕
算法复杂度:
平均性能:O(nlogn)
稳定性:
稳定
*/
#include<iostream>
using namespace std;
void merge(int a[], int low, int mid, int high) {
int R[20];
int i = low, j = mid + 1, k = low; //测试的时候写成了k=0,结果答案错的离谱
for (; i <= mid && j <= high; k++) {
if (a[i] < a[j]) R[k] = a[i++];
else R[k] = a[j++];
}
while (i <= mid) R[k++] = a[i++];
while (j <= high) R[k++] = a[j++];
for (int i = low; i <= high; i++)
a[i] = R[i];
}
void Recursive_Merge_Sort(int a[], int low, int high) { //递归法
int mid;
if (low < high) {
mid = (low+high) / 2;
Recursive_Merge_Sort(a, low, mid);
Recursive_Merge_Sort(a, mid+1, high);
merge(a, low, mid, high);
}
}
void Merge_Sort(int a[], int n) { //非递归法,方法更直接,直接开始就两两组合
int low = 0, high, mid;
int size = 1; //用来控制每次合并的数据个数
while (size <= n - 1) {
low = 0;
while (low + size <= n-1) { //最后一组的下标加上距离
mid = low + size - 1; //跟递归的方法一样
high = mid + size;
if (high > n-1) high = n-1; //单独处理下最后一组数据
merge(a, low, mid, high);
low = high + 1; //重新下一组组合
}
size *= 2; //数据个数
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
// cout << N;
//Recursive_Merge_Sort(num, 0, N-1);
Merge_Sort(num, N);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}
/* 排序算法-4
名称:快速排序
方法:
通过一趟排序将要排序的数据分割成独立的两部分,
其中一部分的所有数据都比另外一部分的所有数据都要小,
然后再按此方法对这两部分数据分别进行快速排序,
整个排序过程可以递归进行,以此达到整个数据变成有序序列。
算法复杂度:
平均性能:O(nlogn)
稳定性:
不稳定
*/
#include<iostream>
using namespace std;
int Partition(int a[], int low, int high) {
int pivot;
pivot = a[low];
while (low < high) {
while (low < high && a[high] >= pivot) high--;
swap(a[high], a[low]); //测试的时候写成了与pivot交换
while (low < high && a[low] <= pivot) low++; //最小的要++
swap(a[high], a[low]);
}
return low;
}
void QSort(int a[], int low, int high) {
int pivot;
if (low < high) {
pivot = Partition(a, low, high); //先找出中轴,是每次它左边全是比他小的值,右边全是比他大的值
QSort(a, low, pivot-1); //左边
QSort(a, pivot+1, high); //右边
}
}
int main() {
int num[] = {20, 10, 90, 80, 40, 60, 50, 30, 70};
int N = sizeof(num)/sizeof(int); //计算数组的长度
QSort(num, 0, N-1);
for (int i = 0; i < N; i++)
cout << num[i] << " ";
cout << endl;
}