原理:2-路插入排序算法是一种变体的插入排序算法,通常用于对数组进行排序。该算法使用两个有序子序列,一个递增有序子序列和一个递减有序子序列,来加快排序过程。
具体实现:
- 将第一个元素作为初始有序序列。
- 从第二个元素开始遍历整个待排序序列,依次将每个元素插入到递增子序列、递减子序列或递增子序列的中间。若:
- 如果元素大于递增子序列的最大值,则直接插入递增子序列末尾。
- 如果元素小于递减子序列的最小值,则直接插入递减子序列开头。
- 如果元素介于递增子序列的最小值和最大值之间,则在递增子序列从大到小依次比较找到元素所在位置,然后将元素插入该位置之后。
- 将有序序列复制回原数组,完成排序。
稳定性:同一元素可能会分别被插入到递增子序列和递减子序列中,而该元素在递增子序列和递减子序列内的相对位置取决于其在原始数组中的位置,因此该算法是稳定的。
时间复杂度:O(nlogn)
适用场景:数据量较小、数据已近部分有序的排序场景。
代码实现:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//2路插入排序
//环形数组思想
template<class T>
void myTwoInsertSort(T arr[], T tem[],int len)
{
int min = 0, max = 0;//记录临时数组中最小和最小的元素用作和待排元素比较
int k = 0;
tem[0] = arr[0];//将数组中的第一个元素当做有序序列中的第一个元素,后面再根据比较后把需要排序的元素加入这个有序序列
for (int i = 1; i < len; i++)
{
int daipai = arr[i];//暂存待排元素,逐个接着进行比较
cout << "待排元素是:" << arr[i] << endl;
if (daipai < arr[min])//排在tem[len-1]位置
{
tem[(min - 1+len) % len] = daipai;//更新tem数组中的最小值
min = (min - 1+len) % len;//更新最小值在数组中的位置
//cout << "此时的最小值是:" << arr[min] << endl;
//cout << "此时的最小值的位置是:" << min << endl;
}
else if (daipai > arr[max])
{
tem[(max + 1) % len] = daipai; //更新tem数组中的最大值
max = (max + 1) % len;//更新最大值在数组中的位置
//cout << "此时的最大值是:" << arr[max] << endl;
//cout << "此时的最大值的位置是:" << max << endl;
}
else//插入值大于最小值且小于最大值
//其实可以把这个待插入值自tem数组中当前元素中的最大值逆时针比较,然后找到待插入值正确的位置
//还有一点,既然这个待插元素要放入有序序列,那么比它大的元素就要依次向后移动一位
//最大值的位置是max,那么最大值移动后就是max+1的位置
//所以用k这个max+1
{
k = (max + 1 + len) % len;//max+1
while (tem[(k - 1 + len) % len] > arr[i])//有序序列自大往小依次和待插元素arr[i]比较
{
//满足待插元素小于有序序列自大往小元素序列元素,往后移动一位
tem[(k + len) % len] =tem[(k-1+ len)% len];
//更新要比较最大值(下标依次减小)序列的下标
k = (k - 1 + len) % len;
}
//待插值找到正确的位置(即待插值大于了一次比较的最大值序列,这个时候k不在移动)后,插入改值
tem[(k + len) % len] = arr[i];
//更新最大值的位置,其实就是往后移动了一位;
max = (max + 1 + len) % len;
//cout << "此时的最大值的位置是:" << max << endl;
}
}
//把暂存数组的元素复制到原来的数组
for (k = 0; k < len; k++)
{
cout << tem[k] << " "<<"*";
//从小到大
arr[k] = tem[(min + k) % len];
cout << arr[k] << " ";
}
}
template<class T>
void myPrint(T arr[], int len)
{
for (int i = 0; i < len; i++)
cout << arr[i] << " ";
cout << endl;
}
int main()
{
int myArr[7] = { 5,6,22,4,6,3,4 };
const int len = sizeof(myArr) / sizeof(int);
int tem[len];
cout << "默认的元素:";
myPrint(myArr, len);
myTwoInsertSort(myArr,tem, len);
cout << "排序后:";
myPrint<int>(myArr, len);//显示指定类型推导
return 0;
}