排序算法(六)二分双插入排序
来源:互联网 发布:中航显示屏编辑软件 编辑:程序博客网 时间:2024/05/29 14:04
1、为减少二分插入排序中的比较及移动次数,可考虑一次以两个数据为单位进行插入。以升序为例,每次插入时先找出两个待插入数据中的较大者,按二分查找法确定其位置,在向后移动已有序记录时一次移动两个位置(因为较小记录肯定将来放在较大记录之前);插入较大数据后再按传统二分插入排序算法在较大数据所处位置与第一条数据所处位置之间插入较小数据。
2、因为在插入较大数据时已经缩小了较小数据的查找范围,同时,在给较大记录移出存放空间时已经提前将一部分本来应该在插入较小数据时才移动的记录提前一趟进行了移动,从而既减少了确定较小记录位置时的比较次数,又减少了移动次数,性能得到了改善。
3、算法描述如下(记录即数据):
假定R[1]到R[i-1]间的记录已经是有序的,现要将从R[i]到最后的所有记录再插入到有序序列中去,可按以下步骤进行:
(1)将 r[i]和 r[i+1]中较大记录放入 max,较小记录放入 min;
(2)用二分查找法确定 max 在 r[1]到 r[i-1]这一段中应该所处的位置,用 high1 表示;
(3)将从 r[high1+1]到 r[i-1]这段中的记录向后移动两条记录的位置;
(4)将 max 放入 r[high1+2];
(5)用二分查找法确定 min 在 r[1]到 r[high1]这一段中应该所处的位置,用 high2 表示;
(6)将从 r[high2+1]到 r[high1]这段中的记录向后移动一条记录的位置;
(7)将 min 放入 r[high2+1];
(8)重复(1)至(8)的过程,直到所有记录插入完为至。
4、本文先介绍一些定义,前面的文章有点乱,而且说明起来比较费力,还是决定按数据结构的方法来贴代码。
下面是一些定义:
#include <iostream>
#include <ctime>
using
namespace
std;
//#define MAXSIZE 50
const
unsigned
int
MAXSIZE = 50;
// 最大长度
typedef
int
KeyType;
// 关键字类型,假定为int
typedef
double
InfoType;
// 其它部分数据类型,此处假定为double
typedef
struct
{
KeyType key;
// 关键字项
InfoType otherinfo;
// 其它数据项
}RedType;
// 记录类型
typedef
struct
{
RedType R[MAXSIZE + 1];
// 0号元素不存放有效数据,R[0]闲置或用作哨兵单元
int
Length;
// 顺序表长度
}SqList;
// 顺序表类型
另外,附上两个函数,作用分别是用随机数初始化顺序表 和 显示当前顺序:
void
RandomInit(SqList* L,
int
nMax
/*= NULL*/
)
{
L->Length = MAXSIZE;
//设置总个数
srand
( (unsigned)
time
(NULL) );
//初始化随机函数
for
(
int
i = 1; i <= L->Length; i++)
//生成原始无序数据
{
if
(nMax != NULL)
{
L->R[i].key =
rand
() % nMax;
}
else
{
L->R[i].key =
rand
();
}
L->R[i].otherinfo =
rand
();
}
}
void
PrintNowOrder(SqList* L)
{
for
(
int
i = 1; i <= L->Length; i++)
{
cout << L->R[i].key <<
"\t"
;
}
cout << endl;
}
5、事实上,我需要多次使用上述内容,所以将上述内容封装成一个类了,此处就不提了,下面是二分双插入排序的实现代码:
// 二分双插入排序算法
void
BinaryDoubleInsertSort(SqList *L)
{
int
i, j, nHigh1, nLow1, nHigh2, nLow2, nMid, nBegin;
RedType nMax, nMin;
// 确定插入的起始位置,偶数个则从第一个开始插入,奇数个则从第二个开始插入
nBegin = (L->Length % 2 == 0) ? 1 : 2;
for
(i = nBegin; i + 1 <= L->Length; i += 2)
{
// 将待插入两条记录按大小分别放入 nMax,nMin
if
(L->R[i].key <= L->R[i+1].key)
{
nMin = L->R[i];
nMax = L->R[i+1];
}
else
{
nMin=L->R[i+1];
nMax=L->R[i];
}
nLow1 = 1;
nHigh1 = i - 1;
// 用二分法确定较大数的位置
while
(nLow1 <= nHigh1)
{
nMid = (nLow1 + nHigh1) / 2;
if
(nMax.key < L->R[nMid].key)
{
nHigh1 = nMid - 1;
}
else
{
nLow1 = nMid + 1;
}
}
// 后移记录,为待插入数提供位置,一次移两个
for
(j = i - 1; j >= nHigh1 + 1; j--)
{
L->R[j + 2] = L->R[j];
}
L->R[nHigh1 + 2] = nMax;
// 插入较大数
nLow2 = 1;
nHigh2 = nHigh1;
// 用二分法确定较小数插入位置,只在较大数位置及起始位置之间查询即可
while
(nLow2 <= nHigh2)
{
nMid = (nLow2 + nHigh2) / 2;
if
(nMin.key < L->R[nMid].key)
{
nHigh2 = nMid - 1;
}
else
{
nLow2 = nMid + 1;
}
}
for
(j = nHigh1;j >= nHigh2 + 1; j-- )
//后移记录,为待插入数提供位置,一次移一个
{
L->R[j + 1] = L->R[j];
}
L->R[nHigh2 + 1] = nMin;
//插入较小数
}
}
- 排序算法(六)二分双插入排序
- 二分插入排序算法
- 排序算法---二分插入排序
- 排序算法--折半插入排序(二分查找排序)
- 【常用排序算法】插入排序/二分插入排序/希尔排序 (Java实现)
- 排序算法二:二分(折半)插入排序
- 排序算法系列五(二分插入排序)
- 排序算法——二分插入排序
- 排序算法三:二分插入排序
- Java排序算法(六):直接插入排序
- Java排序算法(六):直接插入排序
- Java排序算法(六):直接插入排序 .
- Java排序算法(六):直接插入排序
- Java排序算法(六):折半插入排序
- 排序算法之插入排序以及二分插入排序
- 排序算法(四)折半插入排序(二分插入排序)
- 八大排序算法学习笔记:插入排序(二分插入排序)
- 三种数组排序算法(冒泡排序、选择排序、插入排序、二分查找法)
- 软件架构————软件质量概述
- Ubuntu下deb包的安装方法
- 455 - Periodic Strings-C-AC
- 史上最全Java表单验证封装类
- JDk 版本
- 排序算法(六)二分双插入排序
- Ubuntu 安装mysql和简单操作
- 第17章 内容协商与转码
- 相同数目的0和1的子数组 Largest subarray with equal number of 0s and 1s
- qlgenerator让“快速查看”可以预览各种类型文本文件
- Android - 访问手机操作系统
- 开源项目--JCIFS
- 世界三大人种
- ubuntu下mysql数据库重启