排序算法

排序算法的动画演示可以在以下网址获取:
  • 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.youkuaiyun.com/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.youkuaiyun.com/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.youkuaiyun.com/qiaofangjie/article/details/7559843
  1. “分解”——将序列每次折半划分
  2. “合并”——将划分后的序列段两两合并后排序
  3. 递归,直至排序完成。
快速排序                快速排序

图片摘自:http://www.cnblogs.com/jingmoxukong/p/4308823.html
http://blog.youkuaiyun.com/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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值