概述
插入排序的核心便是一个有序表,不断将新的记录插入到有序表合适的位置,从而使得有序表记录数加一。
直接插入排序
void InsertSort(int* L)
{
int temp;//设置一个临时变量
for (int i = 0; i < num - 1; i++)//前i个数已经有序
{
if (L[i + 1] < L[i])//若i+1个数小于第i个数,则开始找合适的位置插入。若大于等于,则第i+1个位置就是合适的位置
{
temp = L[i + 1];//将需要插入的数存储进临时变量
int j;
for (j = i; L[j] >= temp && j>=0; j--)L[j + 1] = L[j];//找到第一个小于待插入数的数,大于待插入数的数后移,插入在它后面
L[j + 1] = temp;
}
}
}
时间复杂度:首先下标为1到n-1的数要和它们前面的数作比较,假如小于则要继续向前作比较找到合适的插入位置。则最理想的情况下,数列为正序,只需比较n-1次。最坏的情况则是倒序,每个数在和前面的数做比较后,还要和前面所有的数作比较后再后移,从1到n-1,分别需要比较2,3,...,n次,根据等差列求和得出需要比较次。则平均时间复杂度为O(n²)。
折半插入
为了减少比较的次数,则用折半的思想去寻找插入位置。
void BInsertSort(int* L)
{
int temp;
for (int i = 0; i < num - 1; i++)
{
if (L[i + 1] < L[i])
{
temp = L[i + 1];
int low = 0, high = i;
int mid;
while (low<=high)
{
mid = (low + high) / 2;
if (temp < L[mid])high = mid - 1;//若待插入值小于中间值,则插入位置在上半部分
else low = mid + 1;//若待插入值大于等于中间值,则插入位置在下半部分
}
for (int j = i; j >= high + 1; j--)L[j + 1] = L[j];
L[high + 1] = temp;
}
}
}
虽然减少了比较的次数,但是移动次数还是不变,时间复杂度任然为O(n²)。
希尔排序
希尔排序也称为缩小增量排序,它的不同在于当待排序列很长时,它通过先将序列变得基本有序,然后再进行插入排序,从而减少时间复杂度。如何将序列变得基本有序,希尔排序选择将待排序列分割成若干子序列再进行直接插入排序,若干子序列合起来就是基本有序。再对整个序列进行插入排序,从而提高效率。怎么将待排序列进行分割,希尔排序引入增量数组这个辅助数组,增量数组中的元素由大变小,最后一定为1,增量表示下标之差。比如,首先将记录数为10的待排序列分割成5个子序列,增量为5,则这5个子序列为{R1,R6},{R2,R7},{R3,R8},{R4,R9},{R5,R10},分别进行插入排序后,增量缩小,对增量为3的子序列进行插入排序,有{R1,R4,R7,R10},{R2,R5,R8},{R3,R6,R9}。增量最后缩小为1,即对整个序列再进行插入排序。
void ShellInsert(int* L,int dlta)
{
for(int i = dlta; i < num; i++)\第dlta+1个记录之前有dlta个有序的子序列,每个子序列都只有一个记录。之后的每个记录都会根据增量在自己的子序列内进行插入排序,写法和普通的插入排序一样
{
int temp;
if(L[i] < L[i - dlta])
{
temp = L[i];
int j;
for(j = i - dlta; j >= 0 && L[j] > temp; j-=dlta)L[j + dlta] = L[j];
L[j + dlta] = temp;
}
}
}
void ShellSort(int* L, int* dlta, int k)
{
for(int i = 0; i < k; i++)
{
ShellInsert(L, dlta[i]);\进行一趟增量为dlta[i]的插入排序
}
}
最后
以上就是调皮铃铛为你收集整理的【数据结构】内部排序之插入排序(直接插入排序,折半插入排序,希尔排序)直接插入排序折半插入希尔排序的全部内容,希望文章能够帮你解决【数据结构】内部排序之插入排序(直接插入排序,折半插入排序,希尔排序)直接插入排序折半插入希尔排序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复