各种排序算法总结

1、冒泡排序

    从第一位开始,依次比较相邻的元素,如果后面一位的数字比这一位小,那就进行调换。经过这样一轮下来,最大的元素就在最后一位了。

    重复以上过程,除了最后一位。

    持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    上代码:

// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(n^2)
// 最优时间复杂度 ---- 如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,可以把最优时间复杂度降低到O(n)
// 平均时间复杂度 ---- O(n^2)
// 所需辅助空间 ------ O(1)
// 稳定性 ------------ 稳定
 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 void swap(vector<int> &a,int i,int j){
 5     int temp = a[i];
 6     a[i]= a[j];
 7     a[j] = temp;
 8 }
 9 int main(){
10     int n;
11     cin>>n;
12     vector<int> a(n);
13     for(int i=0;i<n;i++){
14         cin>>a[i];
15     }
16     for(int i=0;i<n-1;i++){
17         for(int j=0;j<n-1-i;j++){
18             if(a[j] > a[j+1]){
19                 swap(a,j,j+1);
20             }
21         }
22     }
23     for(int i=0;i<n;i++){
24         cout<<a[i]<<endl;
25     }
26 }

2、鸡尾酒排序

    从低到高再从高到低,前半轮将最大元素放在最后,后半轮将最小元素放在前面。

   上代码:



// 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- 如果序列在一开始已经大部分排序过的话,会接近O(n) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 稳定

1
#include <iostream> 2 #include <vector> 3 using namespace std; 4 void swap(vector<int> &a,int i,int j){ 5 int temp = a[i]; 6 a[i]= a[j]; 7 a[j] = temp; 8 } 9 int main(){ 10 int n; 11 cin>>n; 12 vector<int> a(n); 13 for(int i=0;i<n;i++){ 14 cin>>a[i]; 15 } 16 int left = 0; 17 int right = n-1; 18 while(left < right){ 19 for(int i=left;i<right;i++){ 20 if(a[i] > a[i+1]){ 21 swap(a,i,i+1); 22 } 23 } 24 right--; 25 for(int i=right;i>left;i--){ 26 if(a[i] > a[i+1]){ 27 swap(a,i,i+1); 28 } 29 } 30 left++; 31 } 32 for(int i=0;i<n;i++){ 33 cout<<a[i]<<endl; 34 } 35 }

3、选择排序

    从第一位开始,找出序列最小的元素,标记。 再与第一位比较,如果比第一位小的话,进行置换操作。

    循环以上步骤,直至最后一位。

   上代码:



// 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- O(n^2) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 不稳定

1
#include <iostream> 2 #include <vector> 3 using namespace std; 4 void swap(vector<int> &a,int i,int j){ 5 int temp = a[i]; 6 a[i]= a[j]; 7 a[j] = temp; 8 } 9 int main(){ 10 int n; 11 cin>>n; 12 vector<int> a(n); 13 for(int i=0;i<n;i++){ 14 cin>>a[i]; 15 } 16 for(int i=0;i<n;i++){ 17 int min = i; 18 for(int j=i+1;j<n;j++){ 19 if(a[i] > a[j]){ 20 min = j; 21 } 22 } 23 if(i != min){ 24 swap(a,i,min); 25 } 26 } 27 for(int i=0;i<n;i++){ 28 cout<<a[i]<<endl; 29 } 30 }

4、插入排序

    从第一个元素开始,该元素被认为是排序好的。

    取下一个元素,从后往前遍历比较,如果该元素大于新元素,则该元素移到下一个位置。重复此步骤,直至找到已排序的元素比新元素小或者等,将新元素插入到该元素位置之后。

   重复以上步骤。

  上代码:


// 分类 ------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- 最坏情况为输入序列是降序排列的,此时时间复杂度O(n^2)
// 最优时间复杂度 ---- 最好情况为输入序列是升序排列的,此时时间复杂度O(n)
// 平均时间复杂度 ---- O(n^2)
// 所需辅助空间 ------ O(1)
// 稳定性 ------------ 稳定
 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 void swap(vector<int> &a,int i,int j){
 5     int temp = a[i];
 6     a[i]= a[j];
 7     a[j] = temp;
 8 }
 9 int main(){
10     int n;
11     cin>>n;
12     vector<int> a(n);
13     for(int i=0;i<n;i++){
14         cin>>a[i];
15     }
16     for(int i=1;i<n;i++){
17         int get = a[i];
18         int j = i - 1;
19         while(j >= 0 && a[j] > get){
20             a[j+1] = a[j];
21             j--;
22         }
23         a[j+1] = get;
24     }
25     for(int i=0;i<n;i++){
26         cout<<a[i]<<endl;
27     }
28 }

拓展:二分插入排序(思想不再赘述)

上代码

// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(n^2)
// 最优时间复杂度 ---- O(nlogn)
// 平均时间复杂度 ---- O(n^2)
// 所需辅助空间 ------ O(1)
// 稳定性 ------------ 稳定

1
#include <iostream> 2 #include <vector> 3 using namespace std; 4 void swap(vector<int> &a,int i,int j){ 5 int temp = a[i]; 6 a[i]= a[j]; 7 a[j] = temp; 8 } 9 int main(){ 10 int n; 11 cin>>n; 12 vector<int> a(n); 13 for(int i=0;i<n;i++){ 14 cin>>a[i]; 15 } 16 for(int i=1;i<n;i++){ 17 int get = a[i]; 18 int left = 0; 19 int right = i - 1; 20 while(left <= right){ 21 int mid = (left + right)/2; 22 if(a[mid] > get){ 23 right = mid - 1; 24 }else{ 25 left = mid + 1; 26 } 27 } 28 for(int j=i-1;j>=left;j--){ 29 a[j+1] = a[j]; 30 } 31 a[left] = get; 32 } 33 for(int i=0;i<n;i++){ 34 cout<<a[i]<<endl; 35 } 36 }

5、快速排序(递归和非递归)

  递归思想:

  1. 从序列中挑出一个元素,作为"基准"(pivot).
  2. 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。
  3. 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。
  4. 上代码:
    
    

    // 分类 ------------ 内部比较排序 // 数据结构 --------- 数组 // 最差时间复杂度 ---- 每次选取的基准都是最大(或最小)的元素,导致每次只划分出了一个分区,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2) // 最优时间复杂度 ---- 每次选取的基准都是中位数,这样每次都均匀的划分出两个分区,只需要logn次划分就能结束递归,时间复杂度为O(nlogn) // 平均时间复杂度 ---- O(nlogn) // 所需辅助空间 ------ 主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度,一般为O(logn),最差为O(n) // 稳定性 ---------- 不稳定

    1
    #include <iostream> 2 #include <vector> 3 using namespace std; 4 void swap(vector<int> &a,int i,int j){ 5 int temp = a[i]; 6 a[i]= a[j]; 7 a[j] = temp; 8 } 9 int getPartition(vector<int> &a,int low,int height){ 10 int i = low - 1; 11 for(int j=low;j<height;j++){ 12 if(a[j] < a[height]){ 13 i = i + 1; 14 swap(a,i,j); 15 } 16 } 17 swap(a,i+1,height); 18 return i+1; 19 } 20 void quickSort(vector<int> &a,int low,int height){ 21 if(low < height){ 22 int mid = getPartition(a,low,height); 23 quickSort(a, low, mid - 1); 24 quickSort(a, mid + 1, height); 25 } 26 } 27 int main(){ 28 int n; 29 cin>>n; 30 vector<int> a(n); 31 for(int i=0;i<n;i++){ 32 cin>>a[i]; 33 } 34 quickSort(a,0,n-1); 35 for(int i=0;i<n;i++){ 36 cout<<a[i]<<endl; 37 } 38 }

    非递归思想:

  5. #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;
    void swap(vector<int> &a,int i,int j){
        int temp = a[i];
        a[i]= a[j];
        a[j] = temp;
    }
    int getPartition(vector<int> &a,int low,int height){
        int i = low - 1;
        for(int j=low;j<height;j++){
            if(a[j] <= a[height]){
                i = i + 1;
                swap(a,i,j);
            }
        }
        swap(a,i+1,height);
        return i+1;
    }
    void quickSort(vector<int> &a,int low,int height){
        stack<int> nums;
        if(low < height){
            int mid = getPartition(a,low,height);
            if(mid - 1 > low){
                nums.push(low);
                nums.push(mid-1);
            }
            if(mid + 1 < height){
                nums.push(mid+1);
                nums.push(height);
            }
            while(!nums.empty()){
                int qheight = nums.top();
                nums.pop();
                int plow = nums.top();
                nums.pop();
                int pqmid = getPartition(a, plow, qheight);
                if (pqmid - 1 > plow)
                {
                    nums.push(plow);
                    nums.push(pqmid - 1);
                }
                if (pqmid + 1 < qheight)
                {
                    nums.push(pqmid + 1);
                    nums.push(qheight);
                }
            }
        }
    }
    int main(){
        int n;
        cin>>n;
        vector<int> a(n);
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        quickSort(a,0,n-1);
        for(int i=0;i<n;i++){
            cout<<a[i]<<endl;
        }
    }
  6. 归并排序(递归)

    归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。

    归并排序的实现分为递归实现非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。非递归(迭代)实现的归并排序首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。

      归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作,归并操作步骤如下:

    1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
    3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    4. 重复步骤3直到某一指针到达序列尾
    5. 将另一序列剩下的所有元素直接复制到合并序列尾
//
//  main.cpp
//  test
//
//  Created by didi on 2018/4/9.
//  Copyright © 2018年 didi. All rights reserved.
//
//递归的归并排序
#include <iostream>
#include <vector>
using namespace std;
void Merge(vector<int> &a,int left,int mid, int right){
    int len = right -left + 1;
    vector<int> temp(len);
    int i = left;
    int j = mid+1;
    int k = 0;
    while(i <= mid && j <= right){
        temp[k++] = a[i] <= a[j] ? a[i++] : a[j++];
    }
    while(i <= mid){
        temp[k++] = a[i++];
    }
    while (j <= right){
        temp[k++] = a[j++];
    }
    for(int l=0;l<len;l++){
        a[left++] = temp[l];
    }
}
void MergeSort(vector<int>&a,int left,int right){
    if(left == right) return;
    int mid = (left + right) /2;
    MergeSort(a,left,mid);
    MergeSort(a,mid+1,right);
    Merge(a,left,mid,right);
}
int main()
{
    int n;
    cin>>n;
    vector<int> a(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    MergeSort(a,0,n-1);
    for(int i=0;i<n;i++){
        cout<<a[i];
    }
}

 

posted @ 2018-03-19 19:14  兔子兔子0125  阅读(182)  评论(0编辑  收藏  举报