简单插入排序

适用于记录较少且基本有序的记录。算法思想:给定一个存在分界线的序列,分界线左边有序,右边无序,依次将右边的没排序的数与左边序列进行比较,插入相应位置,再对分界线做出相应调整,下面用图来说明。

代码如下:

时间复杂度:最好情况O(n),最坏O(n^2)。

希尔排序

希尔排序是改进后的简单插入排序。算法思想:将序列分组排序,最后在进行一次简单插入排序。

至于如何分组,下面我将用图向大家展示

这些数的下标从0开始,即0,3 ,6,9为一组,1,4,7为一组,2,5,8为一组。也就是gap%3下标相等的为一组。gap=gap/3+1.

代码如下:

void ShellSort(int *a, size_t size)    //希尔排序
{
  assert(a);
  int gap = size;
  while (gap > 1)
  {
      gap = gap / 3 + 1;
      for (int i = gap; i < size; ++i)
     {
       int index = i;
       int tem = a[index];
       int end = index - gap;
       while (end >= 0 && tem < a[end])
       {
          a[end + gap] = a[end];
          end -= gap;
       }
       a[end + gap] = tem;
     }
  }
}

时间复杂度为O(n^1.5)

选择排序

算法思想:每次循环找到最小值,并交换。

代码如下:

void SelectSort(int *a, size_t size)
{
   assert(a);
   for (int i = 0; i < size; ++i)
   {
      int minindex = i;
      int tem;
      for (int j = i + 1; j < size; ++j)
      {
         if (a[j] < a[minindex])
         {
            minindex = j;
            tem = a[minindex];
            a[minindex] = a[i];
            a[i] = tem;
         }
      }
   }
}

时间复杂度O(n^2)

快速排序

算法思想:选取key,将key调整到一个合理的位置,使得左边全部小于key,右边全部大于key;

如何将key调整到合适位置,这里用到三数取中的方法。

注意:如果序列基本有序或序列个数较少,则可以采用简单插入排序,因为快速排序对于这些情况效率不高;

代码如下:

int GetMidIndex(int *a, int left, int right)     /////////三数取中/////////
{
   assert(a);
   int mid=left+(right-left)/2;
   if (left < right)
   {
      if (a[mid] < a[left])
         return left;
      else if (a[mid] < a[right])
         return mid;
      else
         return right;
   }
   else
   {
      if (a[mid] < a[right])
         return right;
      else if (a[mid] < a[left])
         return mid;
      else
         return left;
   }
}

int PartionSort(int *a, int left, int right)
{
   int midIndex = GetMidIndex(a, left, right);
   swap(a[midIndex], a[right]);
   int cur = left;
   int prev = left - 1;
   while (cur < right)
   {
      if (a[cur] < a[right] && ++prev != cur)
      {
         swap(a[cur], a[prev]);
      }
      ++cur;
   }
   ++prev;
   swap(a[prev], a[right]);
   return prev;
}

void QuickSort(int *a,int left,int right)
{
   assert(a);
   int size = right - left + 1;
   if (right - left > 13)        //////////优化:当长度大于13时采用快排,小于13则退化为简单插入排序////////////
   {
      int boundary = PartionSort(a, left, right);
      QuickSort(a, left, boundary - 1);
      QuickSort(a, boundary + 1, right);
   }
   else
      InsertSort(a, size);   /////简单插入排序
}

冒泡排序

算法思想:两两比较再交换,一趟排序下来只能找到一个最大,其余都是乱序,再重复这样做就可以按照从小到大的顺序排下来。

代码如下:

void BubbleSort(int *a, size_t size)
{
   assert(a); 
   for (int i = 0; i < size; i++)
   {
      for (int j = 0; j = size - 1 - i; j++)
      {
         if (a[j] > a[j + 1])
         {
            int tem = a[j + 1];
            a[j + 1] = a[j];
            a[j] = tem;
         }
      }
   }
}

以上冒泡排序有一个效率问题,当序列基本接近有序时,则不需要进行排序,以上代码则会进行不断的比较,影响效率,因此做以下改进,设一个布尔型变量flag,

如果一次循环中没有交换过元素,则说明已经排好序.

优化:

void BubbleSort(int *a, size_t size)
{
   assert(a);

bool flag=true;
   for (int i = 0; i < size; i++)
   {

      bool flag=false;
      for (int j = 0; j = size - 1 - i; j++)
      {
         if (a[j] > a[j + 1])
         {
            int tem = a[j + 1];
            a[j + 1] = a[j];
            a[j] = tem;

          bool flag=true;
         }
      }
   }
}

堆排序

算法思想:将待排序列建成大堆,再将堆顶数据与堆的最后一个叶子节点的数据交换,再重新调整为大堆,每次堆的数据个数减1。

依次类推......

代码如下:

void HeapSort(int *a, size_t size)    //堆排序
{
   assert(a);
   for (int i = (size - 2) / 2; i >= 0; --i)
   {
      Adjustdown(a, size, i);
   }
   for (int i = 0; i < size; ++i)
   {
      swap(a[0], a[size - i - 1]);
      Adjustdown(a, size - i - 1, 0);
   }
}

/////////建大堆/////////

void Adjustdown(int *a, size_t size, int root)
{
   int child = 2 * root + 1;
   while (child < size)
   {
      if (child + 1 < size && a[child + 1] > a[child])
         {
         ++child;
      }
      if (a[child]>a[root])
      {
         swap(a[child], a[root]);
         root = child;
         child = 2 * root + 1;
      }
      else
      {
        break;
      }
   }
}

c++实现排序(简单插入,希尔,选择,快速,冒泡,堆排)的更多相关文章

  1. Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等

    本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排 ...

  2. 排序算法练习--JAVA(:内部排序:插入、选择、冒泡、快速排序)

    排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... 内部排序: 插入排序:直接插入排序 选 ...

  3. 用Python实现十大经典排序算法-插入、选择、快速、冒泡、归并等

    本文来用图文的方式详细讲解了Python十大经典排序算法 —— 插入排序.选择排序.快速排序.冒泡排序.归并排序.希尔排序.插入排序.桶排序.基数排序.计数排序算法,想要学习的你们,继续阅读下去吧,如 ...

  4. 2020-03-25:快排、堆排和归并都是O(nlog n)的算法,为何JDK选择快速排序?

    福哥答案2020-03-26: 口诀如下:冒选插希快 堆归计桶基(冒泡,选择,插入,希尔,快速,堆,归并,计数,桶,基数)冒线 平平 稳常小选平 平平 不常小插线 平平 稳常序希线 四组 不常组快四 ...

  5. java 基础排序(冒泡、插入、选择、快速)算法回顾

    java 基础排序(冒泡.插入.选择.快速)算法回顾 冒泡排序 private static void bubbleSort(int[] array) { int temp; for (int i = ...

  6. 【PHP数据结构】插入类排序:简单插入、希尔排序

    总算进入我们的排序相关算法的学习了.相信不管是系统学习过的还是没有系统学习过算法的朋友都会听说过许多非常出名的排序算法,当然,我们今天入门的内容并不是直接先从最常见的那个算法说起,而是按照一定的规则一 ...

  7. 八大排序方法汇总(选择排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序、堆排序,归并排序,计数排序)

    2013-08-22 14:55:33 八大排序方法汇总(选择排序-简单选择排序.堆排序,插入排序-简单插入排序.shell排序,交换排序-冒泡排序.快速排序,归并排序,计数排序). 插入排序还可以和 ...

  8. 选择排序—简单选择排序(Simple Selection Sort)

    基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素 ...

  9. 选择排序—简单选择排序(Simple Selection Sort)原理以及Java实现

    基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素 ...

  10. [译]async/await中使用阻塞式代码导致死锁 百万数据排序:优化的选择排序(堆排序)

    [译]async/await中使用阻塞式代码导致死锁 这篇博文主要是讲解在async/await中使用阻塞式代码导致死锁的问题,以及如何避免出现这种死锁.内容主要是从作者Stephen Cleary的 ...

随机推荐

  1. [moka同学摘录]Yii2.0开发初学者必看

    想要了解更多YII,PHP方面内容,请关注本博客. 基础总结 1.修改默认控制器/方法 yii默认是site控制器,可以在web.php中设置$config中的'defaultRoute'='xxxx ...

  2. jquery TypeError: 'undefined' is not a function (evaluating 'elem.nodeName.toLowerCase()') [jquery.js:1904]错误原因

    今天,某个环境报了个js错误,TypeError: 'undefined' is not a function (evaluating 'elem.nodeName.toLowerCase()') [ ...

  3. FME中Cass扩展属性转Shp的方法

    问题:真受不了CAD中的注记,只能方便显示,难于数据交互.好在Cass把属性信息基本写在扩展属性中,但显示又成问题了.此事难两全!我们通过查看实体属性,需要把宗地界线的扩展属性提取出来.即组码为-3, ...

  4. Snort - manual 笔记(二)

    1.5 Packet Acquisition Snort 2.9 引入 DAQ 代替直接调用 libpcap . 有两种网卡特性会影响 Snort : "Large Receive Offl ...

  5. C语言指针传递详解

    传递指针可以让多个函数访问指针所引用的对象,而不用把对象声明为全局可访问,要在某个函数中修改数据,需要用指针传递数据,当数据是需要修改的指针的时候,就要传递指针的指针,传递参数(包括指针)的时候,传递 ...

  6. 【读书笔记】iOS-忽略编译警告

    一,忽略编译警告的命令. -w   禁止掉所有的编译警告. -Wno-unused-variable  只禁止掉未使用的变量的编译警告. 二,忽略编译警告的方法. targets--->Buil ...

  7. IOS 简单动画 首尾式动画

    首尾式动画 首尾式动画即通过实现控件由初始状态到结束状态的过程.(主要表现在控件的Frame 透明度 ) // // ViewController.m // CX 简单动画 // // Created ...

  8. iOS Block(一)

    Block使用总结: 1.格式: ReturnType (^ BlockName)(参数…); //例: int (^ BFunc) (int a, int b); 2.block赋值: block名 ...

  9. runtime之消息转发

    前言 在上一篇文章中我们初尝了runtime的黑魔法,可以在程序编译阶段就获取到成员变量的名字,特性以及动态的给对象增加属性等等,在接下来中我们进一步了解OC的消息发送机制.如果之前没接触过runti ...

  10. iOS的高德地图标注特定位置

    在开发时有时候遇到项目里面需要展示公司的位置,这时如果导入百度地图什么的就太浪费资源,而且还占内存 这时只要调用自动高德地图的就行了 自己写一个控制器,导入框架 现在导入系统框架只要多打次就能出来了, ...