排序总结

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、选择排序

/* 排序算法-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、插入排序

/* 排序算法-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;
} 


7、快速排序

/* 排序算法-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;
} 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值