插入排序

来源:互联网 发布:淘宝网招聘 编辑:程序博客网 时间:2024/05/15 17:02

一、插入排序描述

插入排序也称为直接插入排序,是最简单的排序算法。

插入排序在处理大数据时并不高效,因为在决定将元素插入哪个位置之前,需要将被插入元素和有序数据集中的其它元素进行比较,这会随着数据集的增大而增加额外的开销;然而插入排序的优点是,当将元素插入一个有序数据集中时,只需要对有序数据集最多进行一次遍历,而不需要完整地运行算法。这个特性使得插入排序在增量排序中非常高效。

二、稳定性

插入排序是稳定的排序方法。

三、复杂度

时间复杂度:O(n^2),n为要排序的元素个数。

空间复杂度:O(1)。

四、基本思想

插入排序的基本思想:假设待排序的记录存放在数组R[1...n]中。初始时,R[1]自成一个有序区,无序区为R[2...n]。从i=2起至i=n为止,依次将R[i]插入当前的有序区R[1...i-1]中,生成n个记录的有序区。

第i-1趟插入排序:通常将一个记录R[i](i=2,...,n-1)插入到当前的有序区,使得插入后仍保证该区间里的记录是按关键字有序的操作,称为第i-1趟插入排序。

排序过程的某一中间时刻,R被划分成两个子区间:R[1...i-1](已排好序的有序区)和R[i...n](当前未排序的部分,可称为无序区)。

插入排序的基本操作是将当前无序区的第1个记录R[i]插入到有序区R[1...i-1]中适当的位置上,使R[1...i]变为新的有序区。因为这种方法每次使有序区增加一个记录,通常称为增量法。

由插入排序的基本思想很容易得到下面简单的方法:

(1)在当前有序区R[1...i-1]中查找R[i]的正确位置k(1<=k<=i-1)。

(2)将R[k...i-1]中的记录后移一个位置,腾出k位置上的空间插入R[i]。

这里使用升序排序,如果R[i]的关键字大于等于R[1...i-1]中所有记录的关键字,则R[i]就是插入位置。

还有一种改进方法,即查找比较操作和记录移动操作交替进行。其具体做法如下:

将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,...,1)的关键字进行比较:

(1)如果R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;

(2)如果R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。

关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟插入排序。

五、实现

// 插入排序(实现一)void insert_sort(int a[], int n){int i, j, temp;for (i = 1; i < n; i++) // 需要选中n-1此{/* 暂存下标为i的数;下标从1开始,因为开始时下标为0的数前面没有任何数,此时认为它是排好序的 */temp = a[i];for (j = i - 1; j >= 0 && temp < a[j]; j--){/* 如果满足条件就往后挪,最坏情况就是temp比a[0]小,它要放置在最前面 */a[i+1] = a[j];}a[j + 1] = temp;/* 找到小标为i的数的放置位置 */}}

// 插入排序(实现二)// 返回值:如果排序成功返回0;否则返回-1.int insert_sort(void *data, <span style="white-space:pre"></span>/* 比较数据 */int size,/* 数据元素个数 */int esize,/* 数据元素大小 */int (*compare)(const void *key1, const void *key2) // 比较方式){char *a = (char*)data;void *key;int i, j;key = (char*)malloc(esize);/* 在栈上分配一个元素 */if (NULL == key)return -1;/* 反复向有序区插入无序区元素 */for (i = 1; i < size; i++){memcpy(key, &a[i * esize], esize);j = i - 1;/* 查找插入元素的插入位置 */while (j >= 0&& compare(&a[j * esize], key) > 0){memcpy(&a[(j + 1) * esize], &a[j * esize], esize);j--;}memcpy(&a[(j + 1) * esize], key, size);}free(key);return 0;}


1 0
原创粉丝点击