常见排序算法

来源:互联网 发布:mac怎么锁定输入法 编辑:程序博客网 时间:2024/05/16 05:08

排序算法作为常用的基本算法,今天就来总结一下各种经典排序算法,这里只贴出代码,对算法的文字描述可以在课本或其它博客上找到很多详尽的叙述,这里直接上代码而不是常见算法书上的伪代码,希望对正在努力学数据结构与算法的朋友们有帮助:

1:冒泡排序

void BubbleSort(T a[], int n){    if(NULL == a || n <= 0)        return;    for(int i = 0; i < n-1; i++)    {        bool isSwap = false; // 一次循环中没有发生交换说明已经有序        for(int j = 0; j < n-1-i; j++)        {            if(a[j] > a[j+1])            {                // swap(a[j], a[j+1]);                T temp = a[j];                a[j] = a[j+1];                a[j+1] = temp;                isSwap = true;            }        }        if(!isSwap)        {            return;        }    }}

2:插入排序

// 类似于扑克牌的安插template<class T>void InsertionSort(T *a, int n){    int in , out;    for(out = 1; out < n; ++out)    {        T  temp = a[out];        in = out;        while(in > 0 && a[in-1] >= temp)        {            a[in] = a[in -1];            --in;        }        a[in] = temp;    }}

3:选择排序

// 与冒泡排序算法类似,不过选择排序是每轮选最小的,对目前最小的做标记,最后才交换,将最小的放在前面void SelectionSort(int array[], const int len)  // O(n*n){    if(NULL != array && len > 0)    {        for(int i = 0; i < len; i++)        {            int min = i;            for(int j = i++; j< len; j++)            {                if(array[j] < array[min])                    min = j;            }            swap(array, min, i);        }    }}

4:归并排序

#include<iostream>using namespace std;void Merge(int a[], int tmp[], int lPos, int rPos, int rEnd){ // 这里merge类似归并两个有序数组,可以参考merge two sorted array方法,减少重复的移动次数,    int i, lEnd, numElements, tmpPos;    lEnd = rPos - 1;    tmpPos = lPos;    numElements = rEnd - lPos + 1;    while(lPos <= lEnd && rPos <= rEnd)    {        if( a[lPos] <= a[rPos] )            tmp[tmpPos++] = a[lPos++];        else            tmp[tmpPos++] = a[rPos++];    }    while(lPos <= lEnd)        tmp[tmpPos++] = a[lPos++];    while(rPos <= rEnd)        tmp[tmpPos++] = a[rPos++];    for(i = 0; i<numElements; i++, rEnd--)        a[rEnd] = tmp[rEnd];}void mSort(int a[], int tmp[], int low, int high){    if(low < high && low >= 0)    {        int mid = (low+high)/2;        mSort(a, tmp, low, mid);        mSort(a, tmp, mid+1, high);        Merge(a, tmp, low, mid+1, high);    }}void MergeSort(int a[], int len){    int *tmp = NULL;    tmp = new int[len];    if(tmp != NULL)    {        mSort(a, tmp, 0, len -1);        delete[] tmp;    }}void print(int a[], int n){    if(a != NULL && n >= 0)    {        for(int i = 0; i < n; i++)        {            cout << a[i] << ' ';        }        cout << endl;    }}int main(){    int a[10] = {3, 2, 54,12, 2, 5,7, 9, 5, 45};    print(a, 10);    MergeSort(a, 10);    print(a, 10);    cout << endl;    return 0;}

5:快速排序
使用了三次取中的方法选取枢轴,避免了当待排序数据基本有序时退化为冒泡排序的情况:

#include <iostream>using namespace std;/*三次取中作为枢轴,避免了当排序数组有序时时间复杂度退化为O(N^2)的情况    注:STL中sort的实现当元素个数少于10个时,调用插入排序参考网站:    http://blog.csdn.net/insistgogo/article/details/7785038    http://baike.baidu.com/link?url=cskKnDW-StS4kn8P_Q_n69RDxqcKcF46JNMdLcALdxWPoTsOO5ZEi-b3FKBocA3ScARIgiVx4ZuiEjXMw2qHa_*/void swap(int& a , int& b){    a=a^b;      b=a^b;      a=a^b;  }/*函数作用:取待排序序列中low、mid、high三个位置上数据,选取他们中间的那个数据作为枢轴*/  int SelectPivotMedianOfThree(int arr[],int low,int high)  {      int mid = low + ((high - low) >> 1);//计算数组中间的元素的下标      //使用三数取中法选择枢轴      if (arr[mid] > arr[high])//目标: arr[mid] <= arr[high]      {          swap(arr[mid],arr[high]);      }      if (arr[low] > arr[high])//目标: arr[low] <= arr[high]      {          swap(arr[low],arr[high]);      }      if (arr[mid] > arr[low]) //目标: arr[low] >= arr[mid]      {          swap(arr[mid],arr[low]);      }      //此时,arr[mid] <= arr[low] <= arr[high]      return arr[low];      //low的位置上保存这三个位置中间的值      //分割时可以直接使用low位置的元素作为枢轴,而不用改变分割函数了  }void Qsort(int a[], int low, int high){    if(a==NULL)        return;    // if (high - low + 1 < 10)   // STL中的代码,如果元素个数比较少,使用插入排序    // {      //     InsertSort(arr,low,high);      //     return;      // }      SelectPivotMedianOfThree(a, low, high);    if(low >= high)    {        return;    }    int first = low;    int last = high;    int key = a[first];    while(first < last)    {        while(first < last && a[last] >= key)        {            --last;        }        a[first] = a[last];        while(first < last && a[first] <= key)        {            ++first;        }        a[last] = a[first];        }    a[first] = key;    Qsort(a, low, first-1);    Qsort(a, first+1, high);}int main(){    int a[] = {57, 68, 59, 52, 72, 28, 96, 33, 24, -90};    for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++)    {        cout << a[i] << " ";    }    cout << endl;    Qsort(a, 0, sizeof(a) / sizeof(a[0]) - 1);    for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++)    {        cout << a[i] << " ";    }    cout << endl;    return 0;}

6:希尔排序

void ShellSort(int array[], int len)  // O(n*n){    int i = 0;    int j = 0;    int k = -1;    int temp = -1;    int gap = len;    do    {        gap = gap / 3 + 1;         for(i=gap; i<len; i+=gap)        {            k = i;            temp = array[k];            for(j=i-gap; (j>=0) && (array[j]>temp); j-=gap)            {                array[j+gap] = array[j];                k = j;            }            array[k] = temp;        }    }while( gap > 1 );}

7:堆排序
也是top-k问题的一种解法:

#include<iostream>using namespace std;void HeapAdjust(int a[], int n, int size){    int nChild = 2*n + 1; // 左孩子    int t;    while(nChild < size)    {        if((nChild+1 < size)&&(a[nChild+1]> a[nChild]))            nChild++;        if(a[nChild]<a[n])            break;        t = a[nChild];        a[nChild] = a[n];        a[n] = t;        n = nChild;        nChild = 2 * n + 1;    }}/* 这里的k指的是top-k问题吗,当k为size或(size-1)时,则是纯正完整的堆排序过程; k<size-1时,则表示取数据中前k大的元素, 没有对所有的元素进行排序,仅部分排序*/void HeapSort(int a[], int size, int k)  {     if(NULL == a || size < 0)        return;    int i;    for(i = size/2-1; i>=0; i--) // 这里要理解好为什么是size/2-1的逻辑        HeapAdjust(a, i, size); // 依次调整堆,其实就是建堆的过程,因此这里没有额外的建堆函数    int t;    int s = size - k;    while(size>s) // 依次找到最大的放置在数组的末尾    {        t = a[size-1];        a[size-1] = a[0];        a[0] = t;        size --;        HeapAdjust(a, 0, size);    }}void print(int a[], int n){    if(NULL == a || n < 0)        return;    for(int i=0; i< n; i++)    {        cout << a[i] << " ";    }}int main(){    int a[16] = {2, 1, 3, 5,4, 4, 2, 6, 13, 12, 1, 10, 21, 20, 96, -1};    HeapSort(a, 16, 16);    print(a, 16); // 全部进行排序    cout << endl;    int b[6] = {2, 1, 3, 20, 96, -1};    HeapSort(b, 6, 3); // 取top3,数组最后三个数是前三大的    print(b, 6);    cout << endl;    int c[6] = {0, 12, 31, 20, 968, -1};    HeapSort(c, 6, 2); // top2    print(c, 6);    cout << endl;}

参考资料:
http://blog.csdn.net/insistgogo/article/details/7785038

0 0
原创粉丝点击