【初探】排序算法


  • 日期:20160626
  • 作者:i.sshe
  • https://github.com/isshe

【初探】排序算法

1. 基础问题

  • 1.1 各个常见排序算法的思想及关键代码?

2. 基础问题解答

2.1 各个排序算法的思想及关键代码?

代码链接:https://github.com/isshe/Blog/tree/master/7_sort20160624

选择排序的思想:

  • A. 从数据中选择一个最小/最大数据, 和第i个位置数据交换位置.
  • B. 重复A操作,直到所有所有数据都被选择了一次.
  • 关键代码:
    for (i = 0; i < num; i++)
    {
         smallest = i;
         for (j = i; j < num; j++)
         {
             if (temp_array[j] < temp_array[smallest])
             {
                 //找最小 or 最大
                 smallest = j;
             }
         }
         //交换
         tempvalue = temp_array[smallest];
         temp_array[smallest] = temp_array[i];
         temp_array[i] = tempvalue;
    }

插入排序的思想:

  • A. 比较要插入数据value和目标数组array(已经排好序)的元素,从后往前比较,如果比value小/大(看升序降序), 把数组的数据往后移动一格.一直比较直到找到value的合适位置.
  • B.把value插入到数组array中.
  • C.重复AB即可插入多个数据.
  • 关键代码:
     for (i = 0; i < num; i++)
     {
          position = i;
          for(j = i-1; j >= 0; j--)
          {
              if (data->array[i] < array[j])
              {
                   position = j;
                   array[j+1] = array[j];
              }
          }
          array[position] = data->array[i];
     }

归并排序的思想: 分治思想

相关博文:归并排序-自顶向下/自底向上

  • A.分解:把一份数据分为两份。像二分查找那样,mid=(front+rear)/2, 向下取整.(此时分为了[front, mid]和[mid+1, rear]两部分)
  • B.解决:对两部分分别进行递归排序.
  • C.合并:这里是递归合并,从最小的两部分开始一个一个取小的/大的(升序降序),放到目标数组中.
  • 缺点:归并排序不是原地的, 需要拷贝整个数组.
  • 模式:分治法.(将原问题分解为类似的子问题, 递归求解后再合并得到原问题的解)
  • 代码:(归并排序个人个人觉得最精华的地方在于合并)

    void merge(int *array, int front, int rear, int *dst_array)
    {
    int a = front;   //第一个部分的头
    int b = (front + rear) / 2; //第一部分的尾
    int x = b + 1;   //第二部分的头
    int y = rear;    //第二部分的尾
    int i = front;   
    
    while(a <= b || x <= y)
    {
         //这一句是最关键的!是精华!
         //合并是:a指向第一部分最小的数据,x指向第二部分最小的;
         //比较两个最小,看哪个更小,更小的放到目标数组。
         //x>y是为了应付第二部分已经空的情况。(空了就不用比较了,直接把第一部分放目标数组)
         if (x > y || (a <= b && array[a] < array[x]))      
         {
             dst_array[i++] = array[a++];
         }
         else
         {
              dst_array[i++] = array[x++];
         }
    }
    
    //把排序好的放回到原数组
    for (i = front; i <= rear; i++)
    {
         array[i] = dst_array[i];
    }
    }

快速排序:分治思想。

  • 相关博文: 【初探】快速排序学习总结
  • 相关博文: 快速排序及三向切分快速排序
  • A. 在数据区域中选择一个基准点k;
  • B. 大于k的放一边A,小于k的放另一边B.
  • C. 再分别在A,B中以相同的策略划分。
    (注:每一次都能排序好一个数据,就是基准点那个)
  • 关键代码:

     while(1)
     {
         while(array[j] >= key && i < j)  //从后往前找比基准小的
         {
             j--;
         }
    
         while(array[i] <= key && i < j)  //从前往后找比基准大的
          {
              i++;
          }
    
           if (i < j)                     //交换
          {
               temp = array[i];
               array[i] = array[j];
               array[j] = temp;
          }
          else
          {
               break;
          }
    }
    //这次的交换能排序好一个数据,即基准。
     temp = array[j]; 
     array[j] = array[begin];
     array[begin] = temp;
    
     //分两部分,继续递归
     quick_sort(array, begin, j-1);
     quick_sort(array, j+1, end);

冒泡排序:

  • A. 比较相邻数据;
  • B. 交换数据;(上浮或下沉)
  • C. 以此反复。每次都能排序好一个数据
  • 代码:

    void bubble_sort(int *array, int num)
    {
     int    i = 0;
     int    j = 0;
     int    temp = 0;
    
     for(i = 0; i < num; i++)
     {
         for(j = num-1; j > i; j--) //这里是从下往上。
         {
              if (array[j] < array[j-1])
              {
                  temp = array[j];
                  array[j] = array[j-1];
                  array[j-1] = temp;
              }
         }
     }
    }

堆排序:关键在于最大最小堆的调整,排序只是循环输出第一个数据。【和二叉树/优先队列相关一起写】

3. 参考资料

  • 《算法基础-打开算法之门》
  • 《啊哈!算法》
  • 《算法(第四版)》

    注:处于学习阶段,有理解错误的地方还望告知。感谢!

你可能感兴趣的:(排序算法,快速排序,归并排序,选择排序,堆排序,【初探】数据结构与算法)