Sort

来源:互联网 发布:二维数组动态分配内存 编辑:程序博客网 时间:2024/06/11 00:31

Sort

Classification

The importance of sorting lies in the fact that data searching can be optimized to a very high level, if data is stored in a sorted manner.

In-place Sorting and Not-in-place Sorting

in-place sorting: do not require any extra space, like bubble sort;

not-in-space sorting: require some extra spaces, like merge sort;

Stable and Unstable Sorting

If a sorting algorithm, after sorting the contents, does not change the sequence of similar content in which they appear, it is called stable sorting.

stable sorting

If a sorting algorithm, after sorting the contents, changes the sequence of similar content in which they appear, it is called unstable sorting.

unstable sorting

Stability of an algorithm matters when we wish to maintain the sequence of original elements, like in a tuple for example.

Adaptive and Non-Adaptive Sorting Algorithm

A sorting algorithm is said to be adaptive, if it takes advantage of already ‘sorted’ elements in the list that is to be sorted. That is, while sorting if the source list has some element already sorted, adaptive algorithms will take this into account and will try not to re-order them.

A non-adaptive algorithm is one which does not take into account the elements which are already sorted. They try to force every single element to be re-ordered to confirm their sortedness.

Selection Sort

插排对小数目数组很适用,如打牌时的整理牌;
in place
TimeComplexity:O(n2)
AuxiliarySpace:O(1)

Iterative:void selectionsort(int arr[], int n){    int i, j;    for (i = 0; i < n - 1; i++)         {        min = i;                                 for(int j = i + 1; j < n; j++)        {            if(arr[j] < arr[min]) min = j;        }        if(min != i)        {            a[min] ^= a[i];            a[i] ^= a[min];            a[min] ^= a[i];        }    }}
Resursive:void selectionsort(int arr[], int n, int i){    if(i == n) return ;    int min = i, temp;    for (int j = i + 1; j < n; j++)       {          if(arr[j] < arr[min]) min = j;       }    if(min == i) selectionsort(arr, n, i + 1);    else    {        temp = arr[min];        arr[min] = arr[i];        arr[i] = temp;        selectionsort(arr, n, i + 1);    }}

Bubble Sort

WorstandAverageCaseTimeComplexity:O(nn).
Worst case occurs when array is reverse sorted.

BestCaseTimeComplexity:O(n).
Best case occurs when array is already sorted.

AuxiliarySpace:O(1)

BoundaryCases: Bubble sort takes minimum time (Order of n) when elements are already sorted.

// 大的往后面冒泡void bubblesort(int arr[], int n){    int exchanged = 1;  // bool 要加<stdbool.h>    for(int i = 0; i < n - 1 && exchanged; i++)    {        exchanged = 0;        for(int j = 0; j < n - 1 - i;j++)        {            if(arr[j] > arr[j + 1])            {                arr[j] ^= arr[j + 1];                arr[j + 1] ^= arr[j];                arr[j] ^= arr[j+1];                exchanged = 1;            }        }    }}

选择排序与冒泡排序:
选择排序是在每一次排序中把当前未排好的最大(小)值与当前最右(左)边值交换;
冒泡排序是在每一次排序中相邻元素交换把最大(小)值冒到最右(左)边;
由于选择排序每次只做一次交换,而冒泡排序则是 n-i-1 次所以一般情况下选择排序效率略高;

更好的选择排序是希尔排序,
最好的内部排序是快速排序,
最好的外部排序是归并排序;

Insertion Sort

TimeComplexity:O(n2)
AuxiliarySpace:O(1)
插入排序是稳定的;

插入排序很形象的一个类比就是我们打牌时整理牌的过程;

// 1. 先用temp标记要插的数,将大于temp的数往后移,再把temp插进去;这样可以避免交换;void insertionsort(int a[], int n){    int i;    for (i = 1; i < n; i++)                  {        if(a[i] < a[i - 1])                      {            int temp = a[i];                        int j = i;                               while(a[j-1] > temp && j)               {                a[j] = a[j-1];                j--;            }            if(j != i) a[j] = temp;        }    }}// 2. 类似冒泡,将要插的数一直和前面的数比较交换;void bubblesort(int a[], int n){    int i;    for (i = 1; i < n; i++)    {        int j = i ;        while(a[j] < a[j-1] && j)        {            a[j] ^= a[j-1];            a[j-1] ^= a[j];            a[j] ^= a[j-1];            j--;        }    }}

插排对于动态序列是极好的

Shell Sort

希尔排序是插排的改进版本;
一次插排是稳定的,希尔排序进行多次插排,就不是稳定的了;
步长的选择对算法速度有很大的决定作用;

void shellsort(int a[], int n){    int i, j, gap;    // 先分组    for (gap = n/2; gap > 0; gap /= 2)    {        // 再分别进行插入排序        for(i = gap; i < n; i++)        {            if(a[i] < a[i - gap])            {                int temp = a[i];                j = i;                while(a[j - gap] > temp && j >= gap)  // 注意是gap                {                    a[j] = a[j - gap];                    j -= gap;                }                if(j != i) a[j] = temp;            }        }    }}

Merge Sort

TimeComplexity:O(nlgn)

void merge(int a[], int l, int m, int r){    int i = l, j = m + 1, k = 0;    int temp[r-l+1];    while(i <= m && j <= r)    {        if(a[i] <= a[j]) temp[k++] = a[i++];        else temp[k++] = a[j++];    }    while(i <= m) temp[k++] = a[i++];    while(j <= r) temp[k++] = a[j++];    for(i = 0; i < k; i++) a[l+i] = temp[i];   // i < r-l+1 也可以;}void mergesort(int a[], int l, int r){    if(l < r)    {        int m = l + (r - l)/2;        mergesort(a, l, m);        mergesort(a, m + 1, r);        merge(a, l, m, r);    }}

bucket sort

// O(n) huge space costvoid bucket_sort(vector<int> &v1){    int max_num = *max_element(v1.begin(), v1.end());    vector<int> arr;    arr.resize(max_num+1);    for (auto i : v1) arr[i]++;    int k = 0;    for (size_t i = 0; i < v1.size(); i++)    {        while (!arr[k])        {            k++;        }        v1[i] = k;        k++;    }}

radix sort

/**   10 9 8 7 6 *   0 1 2 3 4 5 6 7 8 9 *   1 0 0 0 0 0 1 1 1 1*   1 1 1 1 1 1 2 3 4 5*   10 6 7 8 9*   0 1 2 3 4 5 6 7 8 9*   4 1 0 0 0 0 0 0 0 0 *   4 5 5 5 5 5 5 5 5 5*   6 7 8 9 10*/void radix_sort(vector<int> &v1){    vector<int> count_t;    count_t.resize(10);    vector<int> temp;    temp = v1;    vector<int> const_temp;    const_temp = temp;    int max_num = *max_element(v1.begin(), v1.end());    int i = 1;    // 确定一个数有几位    while (i <= max_num)    {        fill(count_t.begin(), count_t.end(), 0);        for (size_t j = 0; j < v1.size(); j++)        {            count_t[temp[j] / i % 10]++;        }        for (size_t j = 1; j < 10; j++)        {            count_t[j] += count_t[j - 1];        }        for (size_t j = v1.size() - 1; j >= 0; j--)        {            const_temp[--(count_t[temp[j] / i % 10])] = temp[j];            if (j == 0) break;        }        for (size_t j = 0; j < v1.size(); j++) temp[j] = const_temp[j];        i *= 10;    }    for (size_t j = 0; j < v1.size(); j++) v1[j] = temp[j];}

quick sort

#include <stdio.h>void swap(int a[], int i, int j){    int t = a[i];    a[i] = a[j];    a[j] = t;}int partition(int a[], int p, int r){    int i = p;    int j = r + 1;    int x = a[p];    while(1){        while(i<r && a[++i]<x);        while(a[--j]>x);        if(i>=j) break;        swap(a,i,j);    }    swap(a, p, j);    return j;}void quicksort(int a[], int p, int r){    if(p<r){        int q = partition(a,p,r);        quicksort(a,p,q-1);        quicksort(a,q+1,r);    }}int main(){    int i;    int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};    int N = 12;    quicksort(a, 0, N-1);    for(i=0; i<N; i++) printf("%d ", a[i]);    printf("\n");    return 0;}
0 0