插入排序的基本思想是:每次将一个待排序的元素插入到已排好序的子表的合适位置上。以下的排序都是按照增序进行排列。
一、插入排序思路
1、假设待排序的元素存放在数组R[0 ...n-1]中,共n个待排元素。在排序的某一刻时, 有序区R[0 ...i-1],无序区R[i ...n-1]。i的初始值为1,即有序区中仅有一个元素R[0]。在该时刻,要做的是将无序区的第一个元素,即R[i]插入到有序区的合适位置,即插入到有序区R[0 ...i-1]。为了将R[i]插入有序区的合适位置,需要逐次和有序区元素比较,直到R[i]>=有序区的某元素停止。在比较过程中,满足R[i]<有序区元素的需要进行位置替换。
直接插入排序的一趟操作是将当前无序区的第一个元素,插入到有序区R[0 ...i-1]的合适位置。然后R[0 ...i]成为新的有序区。
二、排序算法
/***********************************************************************
* FUNCTION: 直接插入排序
* AUTHOR: zhuzi
* DATE: 2018-5-01
* VERSION: v1.0
* NOTES:
* MODIFICATION:
**********************************************************************/
#include <iostream>
using namespace std;
typedef int KeyType;
typedef int InfoType;
typedef struct
{
KeyType key;
InfoType data;
}RecType;
/*********************************************************************
* function: 直接插入排序
* parameters: RecType R[], 待排序数组
int n, 数组个数
* return value: 无
**********************************************************************/
void InsertSort1(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;
}
}
/*********************************************************************
* function: 输出元素
* parameters: RecType R[], 有序区数组
int n, 数组元素个数
* return value: 无
**********************************************************************/
void print(RecType R[], int n)
{
for(int i = 0; i < n ; i++)
{
cout << "R[" << i << "] <" << R[i].key << "," << R[i].data << ">" << endl;
}
}
int main(int argc, char *argv[])
{
RecType RT[] = {{1,11},{3,33},{2,22},{5,55},{7,77},{8,88}};
InsertSort1(RT, sizeof(RT)/sizeof(RT[0]));
print(RT, sizeof(RT)/sizeof(RT[0]) );
return 0;
}
三、算法分析
直接插入算法由两重循环构成,对于具有n个元素的表,外循环要进行n-1趟排序。每一趟排序中,仅当带插入元素R[i].key>=R[i-1].key时,才不会进入内循环,即不用进行元素移动。
若初始数据为正序,则在每趟排序中比较一次,不会进入内循环,但会执行tmp = R[i]; R[j + 1] = tmp; 即移动两次。正序插入排序中,关键字比较次数为:n-1,元素移动次数为2(n-1)。
若初始数据为逆序,则在每趟排序中需要比较i次,移动i+2次。逆序插入时,关键字比较次数为:n(n-1)/2 = O(n^2), 元素移动次数为:(n-1)(n-4)/2=O(n^2)。
算法的平均复杂度是O(n^2),因为平均的比较次数为i/2, 平均的移动次数为i/2+2,故平均时间复杂度约为O(n^2)。(i/2+i/2+2)=(i+2)=(n-1)(n-4)/2=O(n^2)