简单插入排序

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

代码如下:

时间复杂度:最好情况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. Java文件编码自动转换工具类(只改变编码,不会改变文件内容)

    本篇随笔主要介绍了一个用java语言写的将一个文件编码转换为另一个编码并不改变文件内容的工具类: 通过读取源文件内容,用URLEncoding重新编码解码的方式实现. public class Cha ...

  2. 为什么.NET感觉上比Java差一点

    其实,我本人很喜欢.NET技术.工作经历中,大部分时间也在使用.NET开发. 这几年,由于工作的原因,开始进入Java+Linux世界. 今年,开始学习Python和Scala. 使用.NET时,有种 ...

  3. Verilog学习笔记基本语法篇(十)········ 常用系统函数

    $display 和 $write 任务 格式: $display (p1,p2,...,pn); $write (p1,p2,..,pn); 这两个函数和系统的任务作用是用来输出信息,即将参数p2到 ...

  4. 如何使用mybatis《三》

    在前边阐述了单独使用mybatis的方法,在实际开发过程中mybatis经常和spring一起使用,即mybatis和spring进行集成,现在我们来看如何集成. mybatis和spring进行集成 ...

  5. Jsoup实现java模拟登陆

    Jsoup实现java模拟登陆 2013-10-29 14:52:05|  分类: web开发|举报|字号 订阅     下载LOFTER我的照片书  |     1:如何获取cookies. 1.1 ...

  6. 调用另一个Activity

    <转>调用另一个Activity Intent对象的使用 范例说明 前一个范例介绍了如何运用切换Layout的方式,进行手机页面间的转换.如果要转换的页面并不单只是背景.颜色或文字内容的不 ...

  7. 【译】Dependency Injection with Autofac

    先说下为什么翻译这篇文章,既定的方向是架构,然后为了学习架构就去学习一些架构模式.设计思想. 突然有一天发现依赖注入这种技能.为了使得架构可测试.易维护.可扩展,需要架构设计为松耦合类型,简单的说也就 ...

  8. jQuery Devrama Slider 幻灯片

    Devrama Slider 是个图像滑块,带有许多非常有趣的特性. 它不仅支持图像还支持 HTML 内容. 响应式 方便 CSS3 转换 转换效果 进度条 高级的预加载和延迟加载 CSS 自定义 用 ...

  9. DAX 2009 for Retail's P job does not work after restoring AX database from another environment.

    This time, it's P job.  We already re-configured profiles, distribution locations, distribution grou ...

  10. java多线程系列2-线程控制

    前面的文章已经介绍了有关线程的调度,接下来介绍如何使用方法对线程进行控制 1.线程休眠 public static void sleep(long millis) /* * 线程休眠 * public ...