需要默写的一些排序算法→_→

需要默写的一些排序算法→_→

快速排序

/*
算法思想:在参加排序的序列中任意选择一个元素(通常称为分界元素或基准元素),把小于或等于
分界元素的所有元素都移到分界元素的前面,把大于分界元素的所有元素都移到分界元素的后面,
这样,当前参加排序的序列就被划分成前后两个子序列,其中前一个子序列中的所有元素都小于后
一个子序列的所有元素,并且分界元素正好处于排序的最终位置上。然后分别对这两个子序列递归
地进行上述排序过程,直到所有元素都处于排序的最终位置上,排序结束。
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

//输出结果 
void printData(vector<int> a);

//将 pivot左边的数都小于他,右边的数都大于他 
int Partition(vector<int>& a, int low, int high)
{
    int pivot;
    
    //其实为了方便直接用第一个数做枢纽值很不好 
    pivot = a[low];
    
    //从线性表的两端交替地向中间扫描
    while (low < high)
    {
        while (low < high && a[high] >= pivot) high--;
        //比枢纽值小,就把他放到枢纽值左边 
        a[low] = a[high];
        while (low < high && a[low] <= pivot) low++;
        //比枢纽值大,就把他放到枢纽值右边 
        a[high] = a[low];
    } 
    // 此时, pivot左边的数据都小于他,右边的数据都大于他 
    a[low] = pivot;
    //返回枢纽值位置 
    return low;
}

void Qsort(vector<int>& a, int low, int high)
{
    int pivotloc; 
    
    if (low < high)
    {
        //设置pivot值,然后排序, 使得 pivot左边的数都小于他,pivot右边的数都大于他, 
        //返回排序后pivot的位置 pivotloc, 然后再对其 两边的数据 递归排序 
        pivotloc = Partition(a, low, high);    
        //枢纽值(pivot)左边的数都小于 pivot, 排序所有小于pivot的值 
        Qsort(a, low, pivotloc - 1); 
        //pivot右边的数都大于pivot, 排序所有大于pivot的值 
        Qsort(a, pivotloc + 1, high);
    } 
}

//启动程序 
void QuickSort(vector<int>& a, int size)
{
    //设置排序的区间 
    Qsort(a, 0, size - 1);
    
    printData(a);
}
 
void printData(vector<int> a)
{
    for (const auto& e : a) {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
    unsigned n = a.size();
    
    //插入排序 
    QuickSort(a, n);
    
    return 0;
}

堆排序

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

void printData(vector<int> a)
{
    for (const auto& e : a) {
        cout << e << " ";
    }
    cout << endl;
}

//调整为大顶堆 
void HeapAdjust(vector<int>& a, int low, int high)
{
    int child;
    int tmp;
    //tmp: 父亲结点; 左结点的索引 < n ; 继续 判断孩子结点  
    // 2 * i : 获得左孩子结点索引 
    for (tmp = a[low]; low * 2 < high; low = child)
    {
        child = low * 2;    //获得左孩子结点索引 
        //如果孩子结点索引 尚未越界, 且  左孩子结点 小于 右孩子 结点    
        //就获得右孩子结点索引 
        if (child != high - 1 && a[child] < a[child + 1]) {
            child++;
        }
        if (tmp < a[child]) {      //父亲 < 孩子 
            a[low] = a[child];     //孩子 替换 父亲结点 
        }
        else {
            break;
        }
    } 
    a[low] = tmp;     //将父亲结点 插入 到比他大的 孩子结点位置.
    
}

//没有使用传引用,不改变 a 
void HeapSort(vector<int>& a, int n)
{
    //建立大顶堆
    for (int i = n / 2; i >= 0; i--)
    {
        HeapAdjust(a, i, n);    
    }
    
    for (int j = n - 1; j > 0; j--)
    {
        
        swap(a[0], a[j]);
        //将 a[1..i] 重新调整为大顶堆
        HeapAdjust(a, 0, j); 
    }
    
    printData(a);
}
 
int main()
{
    vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
    unsigned n = a.size();
    
    //插入排序 
    HeapSort(a, n);
    
    return 0;
}

不懂可以看这个: https://www.cnblogs.com/0zcl/p/6737944.html

归并排序

#include <iostream>
#include <cstring>
using namespace std;

int test[100] = { 0 };

void Merge(int *test, int lo, int mid, int hi); 
void MergeSort(int *test, int lo, int hi) {
    if (hi - lo < 2) return;
    int mid = (lo + hi) >> 1;
    MergeSort(test, lo, mid);                           //对前半段排序
    MergeSort(test, mid, hi);                           //对后半段排序
    Merge(test, lo, mid, hi);                           //归并
}

//归并---O(nlogn), T(n) = 2T(n/2) + O(n)
void Merge(int *test, int lo, int mid, int hi) {
    //A用来存放合并后的向量,B,C进行比较(前后子向量比较)
    int  *A = test + lo;          //合并后的向量A[0,hi-lo) = int s[lo,hi)
    int lb = mid - lo;
    int  *B = new int [lb];        //前子向量 B[0,lb) = int s[lo,mi)
    for (int i = 0; i < lb; B[i] = A[i++]);   //复制前子向量
    int lc = hi - mid;
    int  *C = test + mid;         //后子向量
    for (int i = 0, j = 0, k = 0; (j < lb || k < lc);) {
        //B[i], C[k]中小者转至A的末尾.        
        //因为C本来就占据A中,不需要考虑提前耗尽情况
        if ((j < lb) && (k >= lc || C[k] >= B[j]))      //C[k]已无或不小
            A[i++] = B[j++];
        if ((k < lc) && (j >= lb || B[j] >= C[k]))      //B[k]已无或不小
            A[i++] = C[k++];
    }
    delete[]B;
}


int main()
{
    //用来测试 非模板写的 归并排序 算法
    
    int Test[13] = { 1, 5, 2, 3, 6, 8, 9, 10, 13, 12, 4, 7, 11 };
    
    MergeSort(Test, 0, 13);
    
    for (int i = 0; i < 13; i++)
        cout << Test[i] << " ";
    cout << endl;

    return 0;

}

插入排序

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

void printData(vector<int> a)
{
    for (const auto& e : a) {
        cout << e << " ";
    }
    cout << endl;
}

//没有使用传引用,不改变 a 
void InsertSort(vector<int> a, int n)
{
    for (int i = 1; i < n; i++)
    {
        if (a[i] < a[i - 1])  //当前选择的数 < 前一个数 
        {                     //就把放到前面去 
            int    j = i - 1;
            int temp = a[i];
            //当前的数跟前面数比较, 一直小,前面的数就一直后移 
            while (j >= 0 && temp < a[j])
            {
                a[j + 1] = a[j];
                j--;
            }
            a[j + 1] = temp; 
        }
    }
    
    printData(a);
}

//折半插入排序, 只是使用折半查找的方法来寻找插入位置
void BinInsertSort(vector<int> a, int n)
{
    int low, high, mid, tmp;
    for (int i = 1; i < n; i++)    
    {
        tmp = a[i];
        low = 0, high = i - 1;
        while (low <= high)
        {
            mid = (low + high) / 2;
            if (tmp > a[mid]) {
                low = mid + 1;
            }
            else {
                high = mid - 1;
            }
        }
        for (int j = i; j > low; j--) {
            a[j] = a[j - 1];          //前移 
        }
        a[low] = tmp;
    }
    
    printData(a);
} 
 
int main()
{
    vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12};
    unsigned n = a.size();
    
    //插入排序 
    InsertSort(a, n);
    
    //折半插入排序
    BinInsertSort(a, n);
    
    return 0;
}

选择排序

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

void printData(vector<int> a)
{
    for (const auto& e : a) {
        cout << e << " ";
    }
    cout << endl;
}

//没有使用传引用,不改变 a 
void ChooseSort(vector<int> a, int size)
{
    int min = 0, i, j;
    for (i = 0; i < size - 1; i++)
    {
        min = i;              //此假设为最小值的下标
        for (j = min + 1; j < size; j++)
        {
            if (a[min] > a[j]) {
                min = j;      //找出当前位置 最小值的下标 
            }
        } 
        //如果假设的最小的下标改变了,就将最小下标位置元素
        //与 i 位置交换,则 i 为当前位置最小的元素
        if (i != min) {
            swap(a[i], a[min]);
        }
    }
    
    printData(a);
}
 
int main()
{
    vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12, 44, 23, 34};
    unsigned n = a.size();
    
    //插入排序 
    ChooseSort(a, n);
    
    return 0;
}

冒泡排序

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

void printData(vector<int> a)
{
    for (const auto& e : a) {
        cout << e << " ";
    }
    cout << endl;
}

//没有使用传引用,不改变 a 
void BubbleSort(vector<int> a, int n)
{
    bool ordered;
    //外层循环 -- 一共进行比较的趟数( n - 1 ) 
    for (int i = 0; i < n - 1; i++)
    {
        ordered = true;
        //每趟需要比较的次数 
        //每次循环后,可以依次得到Max,次Max, 次次max...... 
        for (int j = 0; j < n - i - 1; j++)
        {
            //每次选出  当前位置元素  应当所在的  最大位置, 并交换
            if (a[j] > a[j + 1]) 
            {
                swap(a[j], a[j + 1]);
                //只要交换,则说明交换前,不是有序
                ordered = false;
            }
        }
        //一次交换都没有,说明已经没有逆序对,则已经有序,直接退出循环! 
        if (ordered) {
            break;
        }
    }
    
    printData(a);
}
 
int main()
{
    vector<int> a = {-1, 2, 5, 6, 3, 10, 8, 20, 15, 12};
    unsigned n = a.size();
    
    //插入排序 
    BubbleSort(a, n);
    
    return 0;
}

 

posted @ 2018-02-26 00:30 douzujun 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值