直接插入排序与二分插入排序的C++实现

1.直接插入排序

直接插入排序的过程可以理解为一个固定长度的数组被分为两个集合,即已排序集合和未排序。

开始时已排序集合为空,而未排序集合即为整个数组。当排序开始后插入一个对象,已排序集合元素数目加1,相应地未排序集合元素数目减1,重复插入过程直至将未排序集合清空为止,这时排序集合就是最终结果。如下图:

C++实现如下,为了使得程序可以对各种基本数据类型都能排序,使用了模板类,注意模板类的类声明和成员函数实现必须在同一个cpp文件里面,不能分开!!

 1 #ifndef INSERTSORT_H
 2 #define INSERTSORT_H
 3 #include <vector>
 4 #include <iostream>
 5 using std::cout;
 6 using std::endl;
 7 using std::vector;
 8
 9 template <typename T>
10 class InsertSort
11 {
12 private:
13     unsigned len;
14     vector<T> list;
15 public:
16     InsertSort(vector<T> _list, unsigned _len)
17     {
18         for (unsigned i = 0; i < _len; ++i) list.push_back(_list[i]);
19         this->len = _len;
20     }
21     void insertSort()
22     {
23         T insertNum;
24         for (unsigned i = 0; i < len; ++i) // Insert number for len times
25         {
26             insertNum = list[i]; // The number is to be inserted
27             unsigned j = i;
28             while (j && insertNum < list[j-1]) // Find the position to insert the target number in
29             {
30                 list[j] = list[j - 1];
31                 --j;
32             }
33             list[j] = insertNum;
34         }
35     }
36     void out()
37     {
38         for (unsigned i = 0; i < len; ++i)
39         {
40             cout << list[i] << " ";
41             if ((i+1)%18 == 0) cout << endl;
42         }
43         cout <<  endl;
44     }
45 };
46 #endif

2.二分插入排序

因为直接插入排序在搜索插入位置的时候,效率很低,对于大数组,尤其不适用,于是采用二分插入排序,又叫折半插入排序,二分插入排序是采用折半查找法寻找要插入的位置。

下面演示了折半查找法在目标数组中确定数字35的位置:

  • 首先确定目标数组的中间位置数字为45
  • 由于45 > 35,所以降原数组折半并取左半部分子数组作为搜索目标,左半部分的中间元素为23
  • 由于23 < 35,所以再折半,选择子数组的有半部分作为搜索目标
  • 而35 < 36,于是确定35的位置在23和36之间。

下面给出C++实现:

 1 #ifndef BINARYINSERTSORT_H
 2 #define BINARYINSERTSORT_H
 3 #include <vector>
 4 using std::vector;
 5 template <typename T>
 6 class BinaryInsertSort
 7 {
 8 private:
 9     int len;
10     vector<T> list;
11 public:
12     BinaryInsertSort(vector<T> _list, int _len)
13     {
14         for (int i = 0; i < _len; ++i) list.push_back(_list[i]);
15         this->len = _len;
16     }
17      void binaryInsertSort()
18      {
19         int middle;
20         for (int i = 0; i < len; ++i)
21         {
22             T insertNum =    list[i];
23             int left = 0;
24             int right = i - 1;
25             while (left <= right)//Find the insertation position with binary search
26             {
27                 middle = (left + right) / 2;
28                 if (insertNum > list[middle])
29                     left = middle + 1;
30                 else
31                     right = middle - 1;
32             }
33             for (int j = i; j > left; --j) list[j] = list[j-1];
34             list[left] = insertNum;
35         }
36      }
37     void out()
38     {
39         for (unsigned i = 0; i < len; ++i)
40         {
41             cout << list[i] << " ";
42             if ((i+1)%18 == 0) cout << endl;
43         }
44         cout <<  endl;
45     }
46 };
47 #endif

3.测试运行

 1 #include "InsertSort.h"
 2 #include "BinaryInsertSort.h"
 3 #include <vector>
 4 using namespace std;
 5
 6 const unsigned numEle = 8;
 7 int data[numEle] = {1,5,7,3,8,2,6,4};
 8
 9
10 int main()
11 {
12     vector<int> testData;
13     for (unsigned i = 0; i < numEle; ++i) testData.push_back(data[i]);
14     //InsertSort<int> test(testData, numEle);
15     //test.insertSort();
16     BinaryInsertSort<int> test(testData, numEle);
17     test.binaryInsertSort();
18     test.out();
19     return 0;
20
21 }

4. 参考文献

左飞:C++数据结构原理与经典问题求解

时间: 2024-08-05 11:33:13

直接插入排序与二分插入排序的C++实现的相关文章

常见排序集合(冒泡排序,选择排序,直接插入排序,二分插入排序,快速排序,希尔排序,归并排序)

一下是一些常见的排序算法: 交换元素(后面算法都有用到): // 交换元素 private static void swap(int[] a, int i, int j) { int temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } 冒泡排序(有优化): // 冒泡排序(优化①,②,③,④) private static void bubbleSort(int[] a) { boolean flag = false;// ①表示整个序列是无序的 for

直接插入排序、二分插入排序、希尔排序、冒泡排序与简单选择排序

一.直接插入排序 稳定,时间复杂度:最好O(n).最差O(n^2).平均O(n^2),空间复杂度O(1) void InsertSort(int L[], int n) { int i, j,key; for (i = 1; i<n; i++) if(L[i] < L[i-1])//需要将L[i]插入到有序表L[0...i-1] { key = L[i]; for(j = i-1; j >= 0 && key < L[j]; j--)//后移 L[j+1] = L[

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

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

我的Java开发学习之旅------&gt;Java经典排序算法之二分插入排序

一.折半插入排序(二分插入排序) 将直接插入排序中寻找A[i]的插入位置的方法改为采用折半比较,即可得到折半插入排序算法.在处理A[i]时,A[0]--A[i-1]已经按关键码值排好序.所谓折半比较,就是在插入A[i]时,取A[i-1/2]的关键码值与A[i]的关键码值进行比较,如果A[i]的关键码值小于A[i-1/2]的关键码值,则说明A[i]只能插入A[0]到A[i-1/2]之间,故可以在A[0]到A[i-1/2-1]之间继续使用折半比较:否则只能插入A[i-1/2]到A[i-1]之间,故可

二分插入排序JAVA实现

package kpp.sort; /** * 当前待插入元素data[i],若data[i]>=data[i-1],则表示排序正常,i++处理下一个元素 * 若data[i]<data[i-1],先保存data[i]至temp,二分查找到适合插入的位置k,从k到i-1的元素顺序右移 * 将temp插入到k * * 分析: * 二分插入排序的比较次数与待排序记录的初始状态无关,仅依赖于记录的个数. * 当n较大时,比直接插入排序的最大比较次数少得多.但大于直接插入排序的最小比较次数. * 算法

二分插入排序

二分插入排序算法 一.基本思想:源自于二分查找,假设表中元素是按升序排列,将待插入的关键字与表中间位置记录的关键字与作比较.如果小于该关键字,则将元素插入后面的子表中,反之,如果大于该关键字,则将元素插入前面的子表中.反复迭代,直至所有关键字全部插入表中. 二.C 语言代码: 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 //对 R[0...n-1] 递增有序进行直接插入排序 5 void binaryInsertSort(RecTy

快速排序/二分插入排序的swift以及Java实现

经常会用到排序的算法,比如:冒泡法,选择法,快速排序,二分插入排序等等.前面两个就不说了,贴出来自己写的快速排序和二分插入排序的Swift及Java的代码实现,喜欢的话control+C拿去用. swift实现快速排序和二分插入排序算法: (想运行的话,直接复制代码,替换掉控制器里的viewDidLoad方法就好了) override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading

Python使用二分插入排序竟然比直接插入排序快99倍!

?? Python使用二分插入排序竟然比直接插入排序快99倍! 之前发布同一个算法,C++竟然比C快8倍! , 有同学提出是因为C++中使用了二分插入排序,于是用python比较了下两种排序差距有多大. 测试结果如下: Python insertion sort took time: 1:39:42.448904Python insertion sort with binary search took time: 0:01:13.263267 代码如下: import datetime impo

优化的直接插入排序(二分查找插入排序,希尔排序)

直接插入排序 (一)概念及实现 直接插入排序的原理:先将原序列分为有序区和无序区,然后再经过比较和后移操作将无序区元素插入到有序区中. 具体如下(实现为升序): 设数组为a[0…n]. 1.        将原序列分成有序区和无序区.a[0…i-1]为有序区,a[i…n] 为无序区.(i从1开始) 2.        从无序区中取出第一个元素,即a[i],在有序区序列中从后向前扫描. 3.        如果有序元素大于a[i],将有序元素后移到下一位置. 4.        重复步骤3,直到找