【0】README

0)本文旨在给出 快速排序 的 源码实现和源码分析(分析它的坑);

2)要知道 在 元素个数小于10的时候,快速排序不如插入排序;注意快速排序选取枢纽元 时 所使用的方法是 三数中值分割法,截止范围为10(也就是,如果排序的数组个数小于10, 就不选择快速排序, 而是选择其他排序方法, 如希尔排序或插入排序);(不能再干货)

3)因为 快速排序是基于分治的,这里通过递归实现了分治,每次递归后,待排序的元素个数都会减少,所以最后都是通过插入排序来完成排序的;

4)快速排序基础 参见http://blog.csdn.net/pacosonswjtu/article/details/48879419, 插入排序基础参见 http://blog.csdn.net/pacosonswjtu/article/details/48879263

Attention)小生的插入排序以 本文中的 插入排序为准,以前写的都不算数(哈哈),因为我发现这个 版本的插入排序太 tm 灵活了,仅此而已;

5)快速选择算法(从n个数中选择第k个最大(小)数),代码实现在文末;快速选择算法 基础知识 参见 http://blog.csdn.net/pacosonswjtu/article/details/48915197

【1】上源码

#include <stdio.h>
#include <malloc.h>#define ElementType intvoid swap(ElementType* a, ElementType* b);
ElementType median3(ElementType* array, int left, int right);
void quicksort(ElementType* array, int left, int right);
void printArray(ElementType* array, int N);
void insertionSort(ElementType* array, int left, int right);// swap array arraynd b.
void swap(ElementType* array, ElementType* b)
{ElementType t;t=*array;*array=*b;*b=t;
}// 3数中值分割法 选出 left center right 分别存储最小,中间,最大值
// 然后 将中位数隐藏到倒数第2个元素
ElementType median3(ElementType* array, int left, int right)
{   int center = (left+right)/2;if(array[left]>array[center]){swap(&array[left], &array[center]);  }if(array[left]>array[right]){swap(&array[left], &array[right]); }if(array[center]>array[right]){swap(&array[center], &array[right]); }/* 将中位数隐藏到倒数第2个元素 */swap(&array[center], &array[right-1]);return array[right-1];
}/* 快速排序 */
void quicksort(ElementType array[], int left, int right)
{int i, j;ElementType pivot; // 枢轴.// if(right-left >= 10) { also you can let lower limit be 10.if(right-left >= 3) { /* rihgt-left>=3,才有三数中值分割法的应用 *//* 三数分割 median3 把最大元放入array[right]了,枢纽元放入array[right-1],最小元放入array[left] */pivot = median3(array, left, right);    i = left; //i 指向最小元.j = right-1; // j 指向枢纽元.for(;;) {while(array[++i] < pivot);    /* (这里必须++i, 不能i++)找大元素,i停在那里,i起始从 left+1 */while(array[--j] > pivot);    /* (这里必须--j, 不能j--)找小元素,j停在那里,j起始从 right-2 */if(i<j){swap(&array[i], &array[j]);    /* 分割结束 */}else{break;}}//key: array[i]最后指向大元素,array[right-1]指向枢纽元,将它们交换;     swap(&array[i], &array[right-1]);  // 交换后, array[i]=枢纽元, 前面的元素小于它, 后面的元素大于它.quicksort(array, left, i-1);       /* 递归进行快速排序 */quicksort(array, i+1, right);        /* 递归进行快速排序 */} else    /* 当数组长度小于cutoff-隔断距离的话,那么就采用插入排序,因为这样效率高些*/{insertionSort(array, left, right);}
}// 插入排序
void insertionSort(ElementType* array, int left, int right)
{int i, j;ElementType temp; for(i=left+1; i<=right; i++) // 下标i 存储无序部分的第一个元素,即下标i-1 存储有序的最后一个元素.{temp = array[i];for(j=i-1; j>=left; j--) // 下标j 初始存储有序部分的最后一个元素,并在有序部分逆向滑动.{if(temp < array[j]){array[j+1] = array[j];}else{break;}}array[j+1] = temp; // who not array[j]? 因为j--执行后 才推出了循环,所以要加回去.}
}/* 打印数组数据 */
void printArray(int* array, int size)
{int i;for(i=0; i<size; i++){printf("%d ", array[i]);}printf("\n");
}
#include "p177_quick_sort.h"int main()
{ElementType array[] = {34, 8, 64, 51, 32, 21, 64, 8};ElementType array2[] = {34, 8, 64, 51, 32, 21, 64, 8};ElementType array3[] = {34, 8, 64, 51, 32, 21, 64, 8};int size=8;    // test for quicksort.printf("\ntest for quicksort towards {34, 8, 64, 51, 32, 21, 64, 8}\n");quicksort(array, 0, size-1);printArray(array, size);   // test for median3printf("\ntest for median3 towards {34, 8, 64, 51, 32, 21, 64, 8}\n");median3(array2, 0, size-1);printArray(array2, size);// test for insertionSortprintf("\ntest for insertionSort towards {34, 8, 64, 51, 32, 21, 64, 8}\n");insertionSort(array3, 0, size-1);printArray(array3, size);
}

【2】review 插入排序代码实现(注意我的输入参数,可能和他家的不一样)

1)参数分析:这个插入排序的源码荔枝 比较灵活,因为输入参数可变,不一定非得认为 left==0,还可以对其子数组进行插入排序;

// 插入排序
void insertionSort(ElementType* array, int left, int right)
{int i, j;ElementType temp; for(i=left+1; i<=right; i++) // 下标i 存储无序部分的第一个元素,即下标i-1 存储有序的最后一个元素.{temp = array[i];for(j=i-1; j>=left; j--) // 下标j 初始存储有序部分的最后一个元素,并在有序部分逆向滑动.{if(temp < array[j]){array[j+1] = array[j];}else{break;}}array[j+1] = temp; // who not array[j]? 因为j--执行后 才推出了循环,所以要加回去.}
}

【3】快速选择算法

1)intro:快速选择算法是从n个数中选择第k个最大(小)数算法,且是快速排序的变体算法,因为快速排序基于递归的分治算法,每轮递归后,都可以确定枢纽元的最终下标位置;所以通过 k 次 快速排序就可以确定 第k 个 最大(小)元素了,而不用对所有 元素进行排序;

2)当元素个数小于10(官方建议取10,不过这里的测试用例取3)的时候:快速排序依然会用到插入排序;

3)快速选择算法分析:快速选择算法 是 快速排序的变体算法,基本的idea是一样的,只不过 快速选择函数 多带了一个输入参数 k值,且在函数末尾要比较 i(因为 array[i] 存储着枢纽值) 和 k的大小以此来确定 该在哪个 数组范围内递归进行快速选择,代码如下:

#include <stdio.h>
#include <malloc.h>#define ElementType int
#define Error(str) printf("\nerror: %s", str)void swap(ElementType* a, ElementType* b);
ElementType median3(ElementType* array, int left, int right);
void quickselect(ElementType* array, int left, int right, int k);
void printArray(ElementType* array, int N);
void insertionSort(ElementType* array, int left, int right);// swap array arraynd b.
void swap(ElementType* array, ElementType* b)
{ElementType t;t=*array;*array=*b;*b=t;
}// 3数中值分割法 选出 left center right 分别存储最小,中间,最大值
// 然后 将中位数隐藏到倒数第2个元素
ElementType median3(ElementType* array, int left, int right)
{   int center = (left+right)/2;if(array[left]>array[center]){swap(&array[left], &array[center]);  }if(array[left]>array[right]){swap(&array[left], &array[right]); }if(array[center]>array[right]){swap(&array[center], &array[right]); }/* 将中位数隐藏到倒数第2个元素 */swap(&array[center], &array[right-1]);return array[right-1];
}/* 快速选择(第k+1个最大元素), 所以如果要选择第k个最大元素,main函数需要传入k-1 */
void quickselect(ElementType array[], int left, int right, int k)
{int i, j;ElementType pivot; // 枢轴.if(k>right){Error("failed quickselect() for k is greater than right.");return;}// if(right-left >= 10) { also you can let lower limit be 10.if(right-left >= 3) { /* rihgt-left>=3,才有三数中值分割法的应用 *//* 三数分割 median3 把最大元放入array[right]了,枢纽元放入array[right-1],最小元放入array[left] */pivot = median3(array, left, right);    i = left; //i 指向最小元.j = right-1; // j 指向枢纽元.for(;;) {while(array[++i] < pivot);    /* (这里必须++i, 不能i++)找大元素,i停在那里,i起始从 left+1 */while(array[--j] > pivot);    /* (这里必须--j, 不能j--)找小元素,j停在那里,j起始从 right-2 */if(i<j){swap(&array[i], &array[j]);    /* 分割结束 */}else{break;}}//key: array[i]最后指向大元素,array[right-1]指向枢纽元,将它们交换;     swap(&array[i], &array[right-1]);  // 交换后, array[i]=枢纽元, 前面的元素小于它, 后面的元素大于它.// 上面的代码和快速排序一样,下面的代码用于基于递归的快速选择if(k > i) {quickselect(array, i+1, right, k);   }else if(k < i){quickselect(array, left, i-1, k);    }// else k == i, bingo.                       } else  /* 当数组长度小于3(10)的话,那么就采用插入排序,因为这样效率高些*/{insertionSort(array, left, right);}
}// 插入排序
void insertionSort(ElementType* array, int left, int right)
{int i, j;ElementType temp; for(i=left+1; i<=right; i++) // 下标i 存储无序部分的第一个元素,即下标i-1 存储有序的最后一个元素.{temp = array[i];for(j=i-1; j>=left; j--) // 下标j 初始存储有序部分的最后一个元素,并在有序部分逆向滑动.{if(temp < array[j]){array[j+1] = array[j];}else{break;}}array[j+1] = temp; // who not array[j]? 因为j--执行后 才推出了循环,所以要加回去.}
}/* 打印数组数据 */
void printArray(int* array, int size)
{int i;for(i=0; i<size; i++){printf("%d ", array[i]);}printf("\n");
}
#include "p185_quick_select.h"int main()
{ElementType array[] = {34, 8, 64, 51, 32, 21, 64, 8,35, 9, 65, 50, 31, 20, 63, 8};         int size=16;    int k = 6;// test for quickselect.printf("\ntest for quickselect towards {34, 8, 64, 51, 32, 21, 64, 8, 35, 9, 65, 50, 31, 20, 63, 8}\n");quickselect(array, 0, size-1, k-1); // pass k-1 not k, you know it.printf("\nthe %dth maximum element is %d \n", k, array[k-1]);
}

ReviewForJob——快速排序(基于插入排序)+快速选择(快速排序变体)相关推荐

  1. [Unity2018.3新功能]Prefab嵌套和变体

    本文节选自洪流学堂公众号专栏<郑洪智的Unity2018课>,未经允许不可转载. 洪流学堂公众号回复专栏,查看更多专栏文章. 大智:"今天我们要学的内容是Prefab中全新的部分 ...

  2. C语言各种排序算法(冒泡排序、快速排序、插入排序、希尔排序、快速排序、 归并排序)

    不知名排序 #include <stdio.h>int main() {int a[18] = {11,5,53,10,26,3,89,32,9,10,1,24,35,56,43,23,7 ...

  3. 十大排序算法详解(一)冒泡排序、选择排序、插入排序、快速排序、希尔排序

    文章目录 一.冒泡排序 1.1 冒泡排序基础[必会知识] 1.2 冒泡排序优化 1.2.1 外循环优化 1.2.2 内循环优化 1.2.3 双向遍历 1.3 冒泡排序的稳定性.复杂度和适用场景 1.3 ...

  4. R语言使用party包中的ctree函数构建条件推理决策树的流程和步骤、条件推理决策树是传统决策树的一个重要变体、条件推理树的分裂是基于显著性测试而不是熵/纯度/同质性度量来选择分裂

    R语言使用party包中的ctree函数构建条件推理决策树的流程和步骤(Conditional inference trees).条件推理决策树是传统决策树的一个重要变体.条件推理树的分裂是基于显著性 ...

  5. C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

    参考:C语言五大排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)动态演示 作者:一只青木呀 发布时间: 2020-09-09 20:18:43 网址:https://blog.csdn.net/ ...

  6. MTK优美代码赏析6:电话本里的快速排序和插入排序算法

    MTK优美代码赏析6:电话本里的快速排序和插入排序算法 记得读书的时候学数据结构和一些程序基础的课程,学了很多的排序算法,当时感觉蛮有趣,也很简单,当大学的教育是以理论为主的,哪些教授们又没给咱举个实 ...

  7. c语言对随机数进行快速排序,C语言自带快速排序对比插入排序

    #include #include #include void getRandomArr (int arr[], int n); void printArr (int arr[], int n); v ...

  8. C语言版--单链表排序,冒泡排序,选择排序,插入排序,快速排序,应有尽有,保证看懂,没有bug!交换节点版本!

    一.废话不多说,直接上代码.如果想看双向循环链表的朋友,可以在我的博客里找. 你好 #include <stdio.h> #include <stdlib.h>typedef ...

  9. 基于深度学习的目标检测综述(单阶段、多阶段、FPN变体、旋转目标检测等)

    随着深度学习的发展,基于深度学习的目标检测方法因其优异的性能已经得到广泛的使用.目前经典的目标检测方法主要包括单阶段(YOLO.SSD.RetinaNet,还有基于关键点的检测方法等)和多阶段方法(F ...

最新文章

  1. Glide的缓存机制
  2. mysql教程联合索引_MySQL中的联合索引学习教程
  3. 20145326蔡馨熤《信息安全系统设计基础》第1周学习总结
  4. 2019年前端的3个趋势
  5. NOSQL的Redis的基础
  6. php获取目录中的所有文件名
  7. 回顾经典,Netflix的推荐系统架构
  8. ttl是什么意思啊_解读:单反和微单的区别是什么?摄影新手应该如何选择?
  9. 金融文本信息情感分析(负面及主体判定)
  10. 网页视频之H264打包为fmp4调研
  11. 人工智能白皮书 附下载地址
  12. js实现中文转拼音的两种方法
  13. 小型项目的微服务架构指南
  14. 华硕主板装系统蓝屏_华硕笔记本电脑重装系统后蓝屏怎么办
  15. 常用的邮箱有哪些?公司邮箱如何申请?
  16. 京东“竖亥小车”秒测商品尺寸重量
  17. Java文件操作大全(包括文件加密,String加密)
  18. 列表中的导航菜单的制作
  19. [架构之路-202]- 常见的需求获取技术=》输出=》用户需求、客户需求(As...., I want.....)、用例图
  20. [前端笔记006]CSS布局之字体 -- font

热门文章

  1. Deltix Round, Spring 2021 D. Love-Hate 随机化 + sos dp(高维前缀和)
  2. 【LOJ6033】棋盘游戏【二分图博弈】
  3. C - Insertion Sort Gym - 101955C
  4. [APIO2016] 划艇(dp + 组合数 + 前缀和优化)
  5. 欢乐纪中A组赛【2019.8.17】
  6. nssl1321,jzoj(初中)2106-买门票【dfs,暴力,字符串】
  7. POJ3784-Running Median(运行中位数)【链表】
  8. jzoj1267-路障【最短路,SPFA】
  9. ssl2345-繁忙的都市
  10. 2019.01.29【NOIP普及组】模拟赛C组总结