您的位置:首页 > 理论基础 > 数据结构算法

内部排序之插入排序(直接插入排序,二分插入排序,希尔插入排序)

2017-03-26 16:40 676 查看

目录

直接插入排序简介及其代码

二分插入排序简介及其代码

希尔插入排序简介及其代码

插入排序总结

直接插入排序简介及其代码

简介:



直接插入排序过程:



代码块:

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef int KeyType;
typedef struct
{
KeyType key;
int data;
}RecType;
void InsertSort(RecType R[], int n)
{
int i, j;
RecType tmp;
for (i = 1; i < n; i++)
{
tmp = R[i];
j = i - 1;
while (j >= 0 && tmp.key < R[j].key)
{
R[j + 1] = R[j];
j--;
}
R[j+1] = tmp;

}
}

int main(void)
{
int i,n = 10;
RecType R[MAXSIZE];
KeyType a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for (i = 0; i < n; i++)
{
R[i].key = a[i];
}
printf("排序前");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
InsertSort(R, n);
printf("排序后");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
system("pause");
return 0;

}


二分插入排序简介及其代码

算法的基本过程:

折半插入排序只是在寻找数的过程中用折半查找法,再移动数据过程中依然用的是传统的插入方法

对于有序的数据序列,采用折半查找法去判断在何处插入i位置上的数据,就大大减少了需要比较的次数。

1)计算 0 ~ i-1 的中间点,用 i 索引处的元素与中间值进行比较,如果 i 索引处的元素大,说明要插入的这个元素应该在中间值和刚加入i索引之间,反之,就是在刚开始的位置 到中间值的位置,这样很简单的完成了折半;

2)在相应的半个范围里面找插入的位置时,不断的用(1)步骤缩小范围,不停的折半,范围依次缩小为 1/2 1/4 1/8 …….快速的确定出第 i 个元素要插在什么地方;

3)确定位置之后,将整个序列后移,并将元素插入到相应位置。

代码块:

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef int KeyType;
typedef struct
{
KeyType key;
int data;
}RecType;
void InsertSort(RecType R[], int n)
{
int i, j, low, high, mid;
RecType tmp;
for (i = 1; i < n; i++)
{
tmp = R[i];
low = 0;
high = i- 1;
while (low <= high)//只有low>high时才会跳出while循环
{
mid = (high + low) / 2;
if (tmp.key < R[mid].key) //要插入的数比R[mid]小,HIGH-1
{
high = mid - 1;
}
else//要插入的数比R[mid]大,LOW+1;
{
low = mid + 1;
}
}
for (j = i - 1; j >= high+1; j--)
{
R[j + 1] = R[j];
}
R[high + 1] = tmp;
}

}
int main(void)
{
int i, n = 10;
RecType R[MAXSIZE];
KeyType a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for (i = 0; i < n; i++)
{
R[i].key = a[i];
}
printf("排序前");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
InsertSort(R, n);
printf("排序后");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
system("pause");
return 0;

}


希尔插入排序及其代码

基本思想

设初始序列有n个元素,选定一个小于n大于或等于1的整数gap作为间隔,将全部元素分成gap个子序列,所有距离为gap的元素放在同一个子序列中,在每个子序列中分别采用直接插入算法进行排序;然后缩小间隔gap,如令gap=gap/2,重复上面的子序列划分和子序列排序动作;直到最后去gap=1,将所有的元素放到一个序列中为止。



希尔插入过程



代码块:

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef int KeyType;
typedef struct
{
KeyType key;
int data;
}RecType;
void ShellSort(RecType R[],int n)
{
int i, j, gap, k;
RecType tmp;
gap = n / 2;
while (gap > 0)
{
for (i = gap; i < n; i++)
{
tmp = R[i];
j = i - gap;
while (j >= 0 && tmp.key < R[j].key)
{
R[j + gap] = R[j];
j = j - gap;
}
R[j + gap] = tmp;
j = j - gap;
}
gap = gap / 2;
}
}
int main(void)
{
int i, n = 11;
RecType R[MAXSIZE];
KeyType a[] = { 10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for (i = 0; i < n; i++)
{
R[i].key = a[i];
}
printf("排序前");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
ShellSort(R, n);
printf("排序后");
for (i = 0; i < n; i++)
{
printf("%d ", R[i].key);
}
printf("\n");
system("pause");
return 0;
}


插入排序总结

1、 直接插入排序:

① 思想:最基本的插入排序,将第i个插入到前i-1个中的适当位置。

② 时间复杂度:T(n) = O(n²)。

③ 空间复杂度:S(n) = O(1)。

④ 稳定性:稳定排序。循环条件while(r[0].key < r[j].key)保证的。

2、 折半插入排序:

① 思想:因为是已经确定了前部分是有序序列,所以在查找插入位置的时候可以用折半查找的方法进行查找,提高效率。

② 时间复杂度:比较时的时间减为O(n㏒n),但是移动元素的时间耗费未变,所以总是得时间复杂度还是O(n²)。

③ 空间复杂度:S(n) = O(1)。

④ 稳定性:稳定排序。

3、 希尔排序:

① 思想:又称缩小增量排序法。把待排序序列分成若干较小的子序列,然后逐个使用直接插入排序法排序,最后再对一个较为有序的序列进行一次排序,主要是为了减少移动的次数,提高效率。原理应该就是从无序到渐渐有序,要比直接从无序到有序移动的次数会少一些。

② 时间复杂度:O(n的1.5次方)

③ 空间复杂度:O(1)

④ 稳定性:不稳定排序。{2,4,1,2},2和1一组4和2一组,进行希尔排序,第一个2和最后一个2会发生位置上的变化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息