排序算法之直接插入排序

142 阅读5分钟
1
、介绍。
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。例如
,
已知待排序的一组记录是:
60,71,49,11,24,3,66
。假设在排序过程中,前
3
个记录已按关键码值递增的次序重新排列,构成一个有序序列:
49,60,71
。将待排序记录中的第
4
个记录(即
11
)插入上述有序序列,以得到一个新的外汇返佣
http://www.kaifx.cn/
4
个记录的有序序列。首先,应找到
11
的插入位置,再进行插入。可以将
11
放入数组的第一个单元
r[0]
中,这个单元称为监视哨,然后从
71
起从右到左查找,
11
小于
71
,将
71
右移一个位置,
11
小于
60
,又将
60
右移一个位置,
11
小于
49
,又再将
49
右移一个位置,这时再将
11
r[0]
的值比较,
11
r[0]
,它的插入位置就是
r[1]
。假设
11
大于第一个值
r[1]
。它的插入位置应该在
r[1]
r[2]
之间,由于
60
已经右移了,留出来的位置正好留给
11.
后面的记录依照同样的方法逐个插入到该有序序列中。若记录数
n,
续进行
n-1
趟排序,才能完成。
直接插入排序是稳定排序,不需要额外内存,空间复杂度
O(1)
。时间复杂度,最佳情况:
O(n)
最差情况:
O(n^2)
平均情况:
O(n^2)
2
、步骤。
(1)
设置监视哨
r[0]
,将待插入记录的值赋值给
r[0]
(2)
设置开始查找的位置
j
(3)
在数组中进行搜索,搜索中将第
j
个记录后移,直至
r[0].key
r[j].key
为止;
(4)
r[0]
插入
r[j+1]
的位置上。
3
、代码。
public static void main(String[] args) {
System.out.println("------
开始
------");
//
生成生成两份随机数组,其中用系统自带的方法进行排序,到时候进行验证。
final int number = 100000;
int[] sortArray = new int[number];
int[] sortArrayCopy = new int[number];
for (int i = 0; i < sortArray.length; i++) {
sortArray = (int) (Math.random() * number);
}
System.arraycopy(sortArray, 0, sortArrayCopy, 0, number);//
数组复制
Arrays.sort(sortArrayCopy);
//
开始排序
long startTime = System.currentTimeMillis();
directInsertSort(sortArray);//
直接插入排序
System.out.println("
花费时间:
" + (System.currentTimeMillis() - startTime));
//
跟系统排序之后数组进行比较,查看是否排序成功。
if (Arrays.equals(sortArray, sortArrayCopy)) {
System.out.println("
排序成功
");
} else {
System.out.println("
排序失败
");
}
System.out.println("------
结束
------");
}
//
直接插入排序 最佳情况:
T(n) = O(n)
最坏情况:
T(n) = O(n2)
平均情况:
T(n) = O(n2)
private static void directInsertSort(int[] array) {
for (int i = 1; i < array.length; i++) {//n-1
轮 第一个无需排序
int curIndex = i;
while (curIndex > 0) {
if (array[curIndex] > array[curIndex - 1]) {
break;
}
int flag = array[curIndex];
array[curIndex] = array[curIndex - 1];
array[curIndex - 1] = flag;
curIndex--;
}
}
}
#include <stdio.h>
void InsertSort(int k[], int n)
{
int i, j, temp;
//i=1,
因为需要
j
指向前一个元素
for(i = 1; i < n; i++)
{
//
进行重新排序,后面的元素小于前面的元素
if (k < k[i-1])
{
temp = k;
//
一个一个地往后推,推到相应位置,然后把
temp
插进去
for (j = i -1; k[j] > temp; j--)
{
k[j+1] = k[j];//
找位置,同时向后推移
}
k[j+1] = temp;
}
}
}
int main(void)
{
int i, a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
InsertSort(a, 10);
printf("
排序后的结果是:
");
for (i = 0; i < 10; i++)
{
printf("%d", a);
}
printf("\n\n");
return 0;
}
#include <iostream>
using namespace std;
void insertSort(int a[],int n){
int tmp,j;
for(int i=1;i<n;i++){//
遍历无序部分
tmp=a;
j=i-1;
//
将无序最左侧的元素和有序部分进行比较
while(j>=0&&tmp<a[j]){
//
将有序部分元素大于
a
的向后移
a[j+1]=a[j];
j--;
}
a[j+1]=tmp;//
把带插入元素放到合适的位置
}
}
int main()
{
int a[]={9,8,7,6,5,4,3,2,1,0};
insertSort(a,10);
for(int i=0;i<10;i++){
cout << a << endl;
}
return 0;
}
#include <stdio.h>
void InsertSort(int arr[],int len)
{
int i = 1;
int temp;
int j;
for(i;i < len;i++)
{
temp = arr;
for(j = i-1;j >= 0 && arr[j] > temp;j--)
{
arr[j + 1] = arr[j];
}
arr[j+1] = temp;
}
}
void Show(int arr[],int len)
{
for(int i = 0;i < len;i++)
{
printf("%d ",arr);
}
}
int main()
{
int arr[] = {87,8,59,24,9};
int len = sizeof(arr)/sizeof(arr[0]);
InsertSort(arr,len);
Show(arr,len);
}
算法分析
时间复杂度:
正序(关键字递增有序):不进入内循环。外循环进行
n-1
趟,也即是比较了
n-1
次(
tmp<a[j]
);每趟进行
2
次赋值(
tmp=a;a[j+1]=tmp;
正序的关键字比较次数最小和元素移动最小次数
反序(关键字递减):关键字比较
R[0
……
都学要比较就是
i
次;内循环移动
R[0
……
都要后移,再加上外面(
tmp=a;a[j+1]=tmp;
)共有
i+2
正序的关键字比较次数最大和元素移动最大次数
对于
R(1<=i<=n-1)
插入到有序区
R[0
……
中,平均比较次数
i/2;
平均移动数
i/2+2
。所以平均时间复杂度:
空间复杂度:
只是用了
i,j,tmp
,与问题规模无关,空间复杂度为
O(1)

更多技术资讯可关注:itheimaGZ获取