排序算法学习整理三(插入)

三、插入排序:

  插入排序是一种非常简单的排序,它的实现难度低于冒泡和选择。(我第一个for循环写出的排序就是插入排序)插入排序类似整理扑克牌,将每一张牌插到其他已经有序的牌中适当的位置。

  基本思想:

    插入排序由N-1趟排序组成,对于P=1到N-1趟,插入排序保证从位置0到位置P上的元素为已排序状态。

    简单的说,就是插入排序总共需要排序N-1趟,从Index为1开始,讲该位置上的元素与之前的元素比较,放入合适的位置,这样循环下来之后,即为有序数组。

  代码实现 

 1 void insertionSort(int *array, int len)
 2 {
 3     for (int i = 1; i < len; i++)
 4     {    //即使i从开始0开始,也不会进入第二个循环。
 5         for (int j = 0; j < i; j++)
 6         {   /*从0~i都是已经排好序的,将array[i]与array[0]~array[i-1]一一进行比较,
 7 找到插入点*/
 8             if (array[i] < array[j])
 9             {    //找到大于array[i]的元素就立即交换(这里存在优化的可能)
10                 array[i] = array[i] ^ array[j];
11                 array[j] = array[i] ^ array[j];
12                 array[i] = array[i] ^ array[j];        //交换
13             }
14         }
15     }
16 }

insertionSort



  代码的问题很明显,就像选择排序为什么会比冒泡快一样,我们可以减少交换次数来优化代码。

  但是不交换怎么排序呢?用赋值语句进行覆盖实现,

    其核心的代码如下:    

    

    for(j = i; j > 0 && temp < array[j-1]; j--)
    {
       array[j] = array[j-1];
    }    array[j] = temp;

    打个比方:

       原数组元素为 : 7 1 2 3

      第一轮:

        1 < 7;执行array[j] = array[j-1]

          1 1 2 3;

        再执行array[j] = temp;

          1 7 2 3;

      第二轮:

        2 < 7;执行array[j] = array[j-1]

          1 2 2 3

        再执行array[j] = temp;

          1 2 7 3

        2 !< 1;退出循环

      第三轮:

        3 < 7;执行array[j] = array[j-1]

          1 2 3 3

        再执行array[j] = temp;

          1 2 3 7        

        3 !< 2;退出循环;

    代码实现:

 1 void insertionSort(int *array, int len)
 2 {
 3     int i, j;
 4     int temp = 0;
 5     for (i = 1; i < len; i++)
 6     {
 7         temp = array[i];     //记录需要插入的元素
 8         for(j = i; j > 0 && temp < array[j-1]; j--)
 9         {   //从array[i]开始和自己的前一个相比较(存在优化的可能)
10         //如果array[i] < array[j-1],就代表array[i]插入的位置不对,
11         //如果temp < array[j-1],不成立,就代表到了array[i]该插入的位置了
12             array[j] = array[j-1];
13         }
14         array[j] = temp;    //找到正确位置后立即插入
15     }
16 }

insertionSor



  现在让我来想一想一个问题,一个数组其元素为  5 1 2 3 4 6 7 8,

     根据插入排序的代码可得到相应的过程

  1. 第一轮:1 5 2 3 4 6 7 8       一次比较,两次赋值
  2. 第二轮:1 2 5 3 4 6 7 8                 两次比较,三次赋值
  3. 第三轮:1 2 3 5 4 6 7 8                 三次比较,四次赋值
  4. 第四轮:1 2 3 4 5 6 7 8                 四次比较,五次赋值

  这个数组的元素除了5原本都是有序的,但是,为了找到5正确的插入位置,总共进行了10次比较,14次赋值。

明眼人都看得出来5的正确位置应该是整个数组的最中间的位置,可是计算机偏偏就是个“瞎子”,那我们该怎么样让这个“瞎子”,知道这个元素是在数组的最中间呢?

这就涉及到到上篇拓展的内容——运用二分查找来这个元素的正确位置。

  这里先贴上二分的核心代码(建议先看懂二分查找再来看二分排序)

        while (left <= right)      //如果走到头都没有找到就退出
        {
            mid = (left+right) / 2;  //记录中间数
            if (arr[mid] > temp)    //和中间数相比较
            {
                right = mid - 1;    //比中间数小就向前走
            }
            else
            {
                left = mid + 1;    //比中间数大就向后走
            }
        }

  这里是用循环来实现二分查找,当然,我们也可以用递归来实现。这里为了节省时间,我就不再多做解释。

从所贴的代码可看出通过二分查找我们确定元素5的正确位置只需要1次比较和5次赋值,大大减少了比较次数和赋值次数。

当然对于二分排序来说采用折半查而减少,为O(nlogn),但是元素交换的次数仍为O(n2),二分排序算法是稳定的。

下面我们来看一下完整的代码:

 1 void insertsort(int *arr, int n)
 2 {
 3     int i, j, temp, left, right, mid;
 4
 5     for (i = 1; i < n; i++)
 6     {
 7         left = 0;
 8         temp = arr[i];
 9         right = i-1;
10
11         while (left <= right)
12         {
13
14             mid = (left+right) / 2;
15             if (arr[mid] > temp)
16             {
17                 right = mid - 1;
18             }
19             else
20             {
21                 left = mid + 1;
22             }
23         }
24
25         for (j = i-1; j > right; j--)
26         {
27             arr[j+1] = arr[j];
28         }
29         arr[right+1] = temp;
30     }
31 }

insertsort



  大家可以自行尝试写一下递归版的二分排序,我在这里就贴代码了。

原文地址:https://www.cnblogs.com/daker-code/p/10322437.html

时间: 2024-07-28 14:44:35

排序算法学习整理三(插入)的相关文章

排序算法学习整理二(选择)

9二.选择排序: 选择排序十分的简单和直观,其的工作原理是每一次从待排序的数组中选出最小(或最大)的一个元素,存放在序列的起始位置.因此,选择排序也是像我们这种萌新最容易写出来的排序算法. 排序步骤: 选出最小的元素 放在数组最前面 选出第二小的元素 放在第二位 重复如此直到完成排序 下面举个栗子: 有一个数组其元素如下 5 1 4 3 2 6 7 0 9,其选择排序流程如下 第一轮: 0 1 4 3 2 6 9 5 7 0最小,0和5换 第二轮: 0 1 4 3 2 6 9 5 7 1最小,不

排序算法学习之堆排序

一.堆与堆排序的产生及定义 在简单选择排序中,每次从n个元素中比较n-1次选取最小的元素,这很好理解,但是前面比较过的数据在之后还要重新比较,这将花费大量的运算时间.堆排序算法就很好的解决了这个问题,堆排序在每次选择到最小记录的同时会根据比较结果对其他数据进行调整,堆排序的时间复杂度为O(NlogN). 堆通常是指二叉堆,即堆是一颗完全二叉树,同时其满足一定性质:每个节点的值大于等于其左右孩子的值(大顶堆),或者每个节点的值小于等于其左右孩子的值(小顶堆).堆在本质上是一个数组,根节点即为a[0

八大排序算法学习笔记:插入排序(一)

插入排序     包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序).属于稳定排序的一种(通俗地讲,就是两个相等的数不会交换位置) . 直接插入排序: 1.算法的伪代码(这样便于理解):     INSERTION-SORT (A, n)             A[1 . . n] for j ←2 to n do key ← A[ j] i ← j – 1 while i > 0 and A[i] > key do A[i+1] ← A[i]

八大排序算法学习笔记:插入排序(二分插入排序)

二分插入排序   也称折半插入排序, 1.基本思想:设数列[0....n]分为两部分一部分是[0...i]为有序序列,另一部分是[i+1.....n]为无序序列,从无序序列中取一个数 x ,利用二分查找算法找到 x 在有序序列中的插入位置并插入,有序序列还是有序的,接下来重复上述步骤,直到无序序列全部插入有序序列 ,这是整个序列只剩下有序序列即有序了. 2.代码:    3.复杂度: 用二分插入排序所要进行的总比较次数为O(lgn),当n较大时,比直接插入排序的最大比较次数小得多,但大于最小比较

数据挖掘算法学习(三)NaiveBayes算法

算法简单介绍 NBC是应用最广的分类算法之中的一个.朴素贝叶斯模型发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率.同一时候,NBC模型所需预计的參数非常少,对缺失数据不太敏感,算法也比較简单. 算法如果 给定目标值时属性之间互相条件独立. 算法输入 训练数据   T={(x1,y1),(x2,y2),--,(xn,yn)} 待分类数据x0=(x0(1),x0(2),--,x0(n))T 算法输出 待分类数据x0的分类结果y0∈{c1,c2,--,ck} 算法思想 weka执行 以we

八大排序算法学习笔记:冒泡排序

冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法. 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 算法原理: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有

算法学习启程三问题

A. 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数(在文件夹中至少缺失一个这样的数-为什么?).在具有足够内在的情况下,如何解决该问题?如果有几个外部的“临时”文件可用,但是仅有几百字节的内存,又该如何解决该问题? B.将一个n元一维向量向左旋转i个位置.例如,当n=8且i=3时,向量abcdefgh旋转为defghabc,简单的代码使用一个n元的中间向量在n步内完成该工作.你能否仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转. C.给

排序算法学习之快速排序

快速排序基本思想:选取一个枢轴元素(图简单可选第一个),通过对序列一次遍历(中间涉及到数的交换),将该枢轴放置到序列合适位置,保证其左边数都比它小,右边数都比它大,然后利用递归思想对其左右两个子序列进行同样排序. 快熟排序的基本实现过程:将枢轴元素key备份,序列头尾各设置一个游标--i和j,尾部游标j先移动(如果选择的最后一个元素为枢轴则i先移),直到遇到比key小的元素,将其移到原枢轴处覆盖之,此时j处元素空着了,然后再对i进行移动,直到遇到比key大的元素,将其移到右边下表为j的空白处 v

常见经典排序算法学习总结,附算法原理及实现代码(插入、shell、冒泡、选择、归并、快排等)

博主在学习过程中深感基础的重要,经典排序算法是数据结构与算法学习过程中重要的一环,这里对笔试面试最常涉及到的7种排序算法(包括插入排序.希尔排序.选择排序.冒泡排序.快速排序.堆排序.归并排序)进行了详解.每一种算法都有基本介绍.算法原理分析.算法代码. 转载请注明出处:http://blog.csdn.net/lsh_2013/article/details/47280135 插入排序 1)算法简介 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过