排序算法

来源:互联网 发布:北航软件学院导师 编辑:程序博客网 时间:2024/05/02 06:45
排序算法的动画演示可以在以下网址获取:
  • http://www.atool.org/sort.php
  • http://zh.visualgo.net/
各种常用排序算法 类别 排序方法 时间复杂度 空间复杂度 稳定性 平均情况 最好情况 最坏情况 辅助存储 插入排序 直接插入 O(n2) O(n) O(n2) O(1) 稳定 shell 排序 O(n1.3) O(n) O(n2) O(1) 不稳定 选择排序 直接选择 O(n2) O(n2) O(n2) O(1) 不稳定 堆排序 O(n log2n) O(n log2n) O(n log2n) O(1) 稳定 交换排序 冒泡排序 O(n2) O(n) O(n2) O(1) 稳定 快速排序 O(n log2n) O(n log2n) O(n2) O(n log2n) 不稳定 归并排序 O(n log2n) O(n log2n) O(n log2n) O(1) 稳定 基数排序 O(d(r+n)) O(d(n+rd)) O(d(r+n)) O(rd+n) 稳定 注:基数排序的复杂度中,r 代表关键字的基数,d 代表长度,n 代表关键字的个数。

冒泡排序

  1. 比较相邻的元素。如果是降序(升序),就交换他们两个。
  2. 对每一对相邻元素作比较,从开始到结尾。则,最后的元素应该会是最大(最小)的数。
  3. 针对所有的元素重复以上的步骤(遍历),除了最后一个。

冒泡排序   冒泡排序   冒泡排序

动画演示转自:http://www.oschina.net/code/snippet_103482_14730

//代码用c++实现;//传入参数:整型数组 list[]; 数组成员个数 n. void BobbleSort(int list[], int n){    for(int i = 0; i < n-1; ++i){        for(int j = 0; j < n-i-1; ++j){            if(list[j] > list[j+1]){                std::swap(list[j],list[j+1]);            }        }    }}

选择排序

  1. 从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
  2. 从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
  3. 以此类推,直到所有元素均排序完毕。

选择排序               选择排序

图片转自:http://blog.csdn.net/cike110120/article/details/46400229

//代码用c++实现;//传入参数:整型数组 list[]; 数组成员个数 n. void SelectSort(int list[], int n){    for(int i = 0; i < n-1; ++i){        int min = i;        for(int j = i+1; j < n; ++j){            if(list[min] > list[j]){                min = j;            }        }        std::swap(list[i],list[min]);    }}

插入排序

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置中
  6. 重复步骤2

插入排序               插入排序

动画选自:http://www.jb51.net/article/30794.htm;
                 http://blog.csdn.net/tiredoy/article/details/39351845;

void InsertSort(int list[], int n){    int in, out;    for(out = 1; out < n; ++out){        int tmp = list[out];        in = out;        while(in > 0 && list[in-1] >= tmp){            list[in] = list[in-1];            --in;        }        list[in] = tmp;    }}

快速排序

  1. 在数据集之中,选择一个元素作为”基准”(pivot)
  2. 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。
  3. 此时基准元素在其排好序后的正确位置
  4. 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

快速排序               快速排序

图片摘自:http://jsdo.it/norahiko/oxIy/fullscreen

// 参数列表中,left 表示最左侧的数据下标;right 表示最右侧数据下标;void QuickSort(int list[], int left, int right){    if(left < right){        int i = left;        int j = right;        int pivot = list[left];//选取 pivot;        while(i < j){            while(i < j && list[j] >= pivot){ //从右向左找第一个小于x的数                j--;            }            if(i < j){                list[i++] = list[j];            }            while(i < j && list[i] < pivot){ //从左向右找第一个大于等于x的数                i++;            }            if(i < j){                list[j--] = list[i];            }        }        list[i] = pivot;//将 pivot 移至中间;        QuickSort(list, left, j-1);//对左侧数据递归快排;        QuickSort(list, j+1, right);//对右侧数据递归快排;    }}

归并排序

> 常见的归并排序的空间复杂度为:O(n);> 空间复杂度为 O(1),需要特殊处理。可参考:http://blog.csdn.net/qiaofangjie/article/details/7559843
  1. “分解”——将序列每次折半划分
  2. “合并”——将划分后的序列段两两合并后排序
  3. 递归,直至排序完成。
快速排序               快速排序

图片摘自:http://www.cnblogs.com/jingmoxukong/p/4308823.html
http://blog.csdn.net/tobeandnottobe/article/details/7192953#t1

void mergeSort(int *data, int l, int r){    int q;    if(l < r){                   //只有一个或无记录时不须排序            q = (int)((l+r)/2);      //将data数组分成两半        mergeSort(data, l, q);   //递归拆分左数组        mergeSort(data, q+1, r); //递归拆分右数组        merge(data, l, q, r);    //合并数组    }}void merge(int *data, int p, int q, int r){    int n1, n2, i, j, k;    int *left=NULL, *right=NULL;    n1 = q-p+1;    n2 = r-q;    left = (int *)malloc(sizeof(int)*(n1));    right = (int *)malloc(sizeof(int)*(n2));    for(i=0; i<n1; i++)  //对左数组赋值        left[i] = data[p+i];    for(j=0; j<n2; j++)  //对右数组赋值        right[j] = data[q+1+j];    i = j = 0;    k = p;    while(i<n1 && j<n2) //将数组元素值两两比较,并合并到data数组    {        if(left[i] <= right[j])            data[k++] = left[i++];        else            data[k++] = right[j++];    }    for(; i<n1; i++) //如果左数组有元素剩余,则将剩余元素合并到data数组        data[k++] = left[i];    for(; j<n2; j++) //如果右数组有元素剩余,则将剩余元素合并到data数组        data[k++] = right[j];}



未完待续~~~



乱入一个二分查找

int BinarySearch(int list[], int n, int x){    int low, high, mid;    low = 0;    high = n-1;    while( low <= high){        mid = (low + high)/2;        if( list[mid] == x){            return mid;     //找到结果;        } else if( list[mid] < x){            low = mid +1;        } else if( list[mid] > x){            high = mid -1;        }    }    return -1;}
0 0