• 理解与应用排序算法(快速排序C实现)


    目录

    一、排序的定义

    二、内排序方法

    三、插入排序

    3.1 直接插入排序

    3.1 折半插入排序

    3.1 链表插入排序

    四、交换排序

    五、起泡排序

    六、快速排序


    一、排序的定义

    稳定排序和非稳定排序

    设文件f=(R1......Ri......Rj......Rn)中记录Ri、Rj(i≠j,i、j=1……n)的key相等,即Ki=Kj。

    若在排序前Ri领先于Rj,排序后Ri仍领先于Rj,则称这种排序是稳定的,其含义是它没有破坏原本已有序的次序。


    内排序和外排序

    若待排文件 f 在计算机的内存储器中,且排序过程也在内存中进行,称这种排序为内排序。

    若排序中的文件存入外存储器,排序过程借助于内外存数据交换(或归并)来完成,则称这种排序为外排序。

    二、内排序方法

    各种内排序方法可归纳为以下五类:

    (1)插入排序

    (2)交换排序

    (3)选择排序

    (4)归并排序

      ......

    三、插入排序

    直接插入排序

    折半插入排序

    链表插入排序

    Shell(希尔)排序

    ……

    3.1 直接插入排序

    设待排文件f=(R1R2......Rn)相应的key集合为k ={k1k2......kn}。

    排序方法

    先将文件中的(R1)看成只含一个记录的有序子文件,然后从R2起,逐个将R2至Rn按key插入到当前有序子文件中,最后得到一个有序的文件。插入的过程上是一个key的比较过程,即每插入一个记录时,将其key与当前有序子表中的key进行比较,找到待插入记录的位置后,将其插入即可。

    设文件记录的key集合k={50,36,66,76,95,12,25,36}

    3.1 折半插入排序

    排序算法的T(n)=O(n2),是内排序时耗最高的时间复杂度。

    折半插入排序方法

    先将(R[1])看成一个子文件,然后依次插入R[2]……R[n]。但在插入R[i]时,子表[R[1]……R[i-1]]已是有序的,查找R[i]在子表中的位置可按折半查找方法进行,从而降低key的比较次数。

    3.1 链表插入排序

      设待排序文件f=(R1 R2……Rn),对应的存储结构为单链表结构:

    表置为空表,然后依次扫描链表中每个结点,设其指针为p,搜索到p结点在当前子表的适当位置,将其插入。

    设含4个记录的链表如图:

    四、交换排序

     “起泡”排序(Bubble Sort)

     “快速”排序(Quick Sort)

    4.1 起泡排序

    设记录key集合k={50,36,66,76,95,12,25,36},排序过程如下:

    4.2 快速排序

    设记录的key集合k={50,36,66,76,36,12,25,95},每次以集合中第一个key为基准的快速排序过程如下:

    五、快速排序实现 

    1. #include
    2. #include
    3. #define N 15
    4. // 函数声明
    5. int quick_sort(int *data, int low, int high);
    6. int partion(int *data, int low, int high);
    7. int compare(const void *p1, const void *p2);
    8. int main(int argc, char *argv[])
    9. {
    10. int i;
    11. int data[N] = {0};
    12. // 使用种子值10初始化随机数生成器
    13. srandom(10);
    14. // 生成随机数组
    15. for(i = 0; i < N; i++){
    16. data[i] = random() % 100;
    17. }
    18. // 打印原始数组
    19. for(i = 0; i < N; i++){
    20. printf("%d ", data[i]);
    21. }
    22. puts("");
    23. // 调用快速排序算法对数组进行排序
    24. quick_sort(data, 0, N-1);
    25. // 打印排序后的数组
    26. for(i = 0; i < N; i++){
    27. printf("%d ", data[i]);
    28. }
    29. puts("");
    30. return 0;
    31. }
    32. // 快速排序的分区函数
    33. int partion(int *data, int low, int high){
    34. int temp = data[low];
    35. while(low < high){
    36. // 从右向左找到第一个比基准值小的元素
    37. while(low < high && temp <= data[high]){
    38. high--;
    39. }
    40. // 将比基准值小的元素移到左边
    41. data[low] = data[high];
    42. // 从左向右找到第一个比基准值大的元素
    43. while(low < high && temp >= data[low]){
    44. low++;
    45. }
    46. // 将比基准值大的元素移到右边
    47. data[high] = data[low];
    48. }
    49. // 将基准值放置到最终位置
    50. data[low] = temp;
    51. return low;
    52. }
    53. // 快速排序函数
    54. int quick_sort(int *data, int low, int high){
    55. int t;
    56. // 检查输入数组是否为空
    57. if(data == NULL){
    58. return -1;
    59. }
    60. // 递归结束条件
    61. if(high <= low){
    62. return 0;
    63. }
    64. // 分区,并获取基准值的位置
    65. t = partion(data, low, high);
    66. // 对基准值左边的子数组进行递归排序
    67. quick_sort(data, low, t-1);
    68. // 对基准值右边的子数组进行递归排序
    69. quick_sort(data, t+1, high);
    70. return 0;
    71. }
    72. // 比较函数,用于qsort函数的排序
    73. int compare(const void *p1, const void *p2){
    74. return (*(const int *)p1 - *(const int *)p2);
    75. }

    注意:

    1、compare函数是为qsort函数准备的,但在这个示例中并未使用qsort。
    2、quick_sort函数返回了0,但在实际应用中,我们通常不需要这个返回值,因为排序函数主要是修改数组的内容。但是,检查数组是否为空并返回-1是一个好的做法,可以捕获潜在的错误。

    六、快速排序测试题

    1、利用快速排序对以下数据进行排序1,5,7,8,3,5,9,4,1,0

    1. #include
    2. #include
    3. int quick_sort(int *data, int low, int high);
    4. int partion(int *data, int low, int high);
    5. int main(int argc, char *argv[])
    6. {
    7. int data[] = {1, 5, 7, 8, 3, 5, 9, 4, 1, 0};
    8. int i;
    9. for(i = 0; i < 10; i++){
    10. printf("%d ", data[i]);
    11. }
    12. puts("");
    13. quick_sort(data, 0, 9);
    14. for(i = 0; i < 10; i++){
    15. printf("%d ", data[i]);
    16. }
    17. puts("");
    18. return 0;
    19. }
    20. int partion(int *data, int low, int high){
    21. int temp = data[low];
    22. while(low < high){
    23. while(low < high && temp <= data[high]){
    24. high--;
    25. }
    26. data[low] = data[high];
    27. while(low < high && temp >= data[low]){
    28. low++;
    29. }
    30. data[high] = data[low];
    31. }
    32. data[low] = temp;
    33. return data[low];
    34. }
    35. int quick_sort(int *data, int low, int high){
    36. int t;
    37. if(data == NULL){
    38. return -1;
    39. }
    40. if(low >= high){
    41. return 0;
    42. }
    43. t = partion(data, low, high);
    44. quick_sort(data, low, t-1);
    45. quick_sort(data, t+1, high);
    46. return 0;
    47. }

  • 相关阅读:
    Open vSwitch with DPDK
    HarmonyOS 开发之———应用程序入口—UIAbility的使用
    Verilog开源项目——百兆以太网交换机(三)Hash模块设计
    react 函数式组件使用 cdn方式
    Chrome浏览器插件开发v3版本第二篇:改变页面布局案例
    绿色债券数据集2016-2021(含交易代码、债券简称、发行规模&期限等多指标数据)
    设计模式概述
    2010款雪佛兰科鲁兹车发动机怠速时车身振动明显
    软件测试知识储备:关于「登录安全」的基础知识,你了解多少?
    Nginx之客户并发数限制解读
  • 原文地址:https://blog.csdn.net/get_p_c_j/article/details/139332368