主题:[原创]我所理解的插入排序算法
goal00001111
[专家分:4030] 发布于 2006-06-20 23:19:00
插入排序是一种简单的排序方法,因为的实现比较简单,所以在数据量较少时应用很广泛。插入排序根据其插入的不同方式,可以分为直接插入排序,折半插入排序,2-路插入排序,表插入排序和希尔排序。在这里我将一一写出各种插入排序的算法代码。
直接插入排序
template <class T>
void InsertSort(T a[], int len)
{
int i, j;
T temp;
for (i=1; i<len; i++)
{
temp = a[i];
for (j=i-1; j>=0 && a[j]>temp; j--)//元素后移
a[j+1] = a[j];
a[j+1] = temp; //插入
}
}
有些算法把a[0]设置为临时数据存放处(即原数组中a[0]未存储元素),这样就可以少进行一些判断,在数据量较大时可以节省一些时间,算法如下:
template <class T>
void InsertSort(T a[], int len)
{
int i, j;
for (i=1; i<len; i++)
{
a[0] = a[i];
for (j=i-1; a[j]>a[0]; j--)
a[j+1] = a[j];
a[j+1] = a[0];
}
}
折半插入排序法
由于插入排序的基本操作是在一个有序表中进行查找和插入,则这个查找操作可以利用折半查找来实现。但是折半插入排序仅减少了元素间的比较次数,而元素的移动次数不变,因此折半插入排序法的时间复杂度仍为O(n^2)。算法如下:
template <class T>
void HalfInsertSort(T a[], int len)
{
int i, j;
int low, high, mid;
T temp;
for (i=1; i<len; i++)
{
temp = a[i];
low = 0;
high = i - 1;
while (low <= high) //在a[low。。。high]中折半查找有序插入的位置
{
mid = (low + high) / 2;
if (a[mid] > temp)
high = mid - 1;
else
low = mid + 1;
} //while
for (j=i-1; j>high; j--)//元素后移
a[j+1] = a[j];
a[high+1] = temp; //插入
}//for
}
希尔排序法
希尔排序法又称缩小增量排序法,它也是插入排序类的方法,但在时间效率上较前面几种插入排序算法有较大的改进。
希尔排序法通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到比较相邻元素的最后一趟排序为止。算法如下:
template <class T>
void ShellSort(T a[], int len)//Shell增量序列h(t)= N/2和h(k) = h(k+1)/2。
{
for (int increase=len/2; increase>0; increase/=2)
{
for (int i=increase; i<len; i++)
{
T temp = a[i];
int j = i;
for (; j>=increase; j-=increase)//元素后移
{
if (temp < a[j-increase])
a[j] = a[j-increase];
else
break;
}
a[j] = temp; //插入
}//for
}//for
}
注:缺2-路插入排序和表插入排序,有意者请补上!谢谢!
最后更新于:2007-04-24 19:12:00
回复列表 (共11个回复)
沙发
雨523 [专家分:200] 发布于 2006-06-21 00:29:00
顶
板凳
脱缰野马 [专家分:10] 发布于 2006-06-26 19:43:00
好帖子,顶上去
3 楼
214 [专家分:0] 发布于 2006-06-27 16:41:00
你的第一个帖子有两个错误 不能运行!!!!
4 楼
goal00001111 [专家分:4030] 发布于 2006-06-27 21:03:00
请指出错误!谢谢!
感觉应该没有错误,因为我都编译过的.
弱弱地问一句,你是不是直接拿去编译,而没有写主程序的.
5 楼
快乐祥子 [专家分:0] 发布于 2006-07-16 23:15:00
不会这么傻吧,冒昧问哈,你插哪个元素啊。
6 楼
goal00001111 [专家分:4030] 发布于 2007-04-22 23:04:00
补充:我上面的希尔排序排序程序中使用的增量序列(increment)是Shell建议的序列h(t)= N/2和h(k) = h(k+1)/2。这个序列并非最好的序列,使用希尔增量时希尔排序的最坏情形运行时间为O(N^2)。Hibbard提出一个稍微不同的增量序列,它在实践(并且理论上)给出更好的结果。他的增量形如1,3,7,…,2^k – 1。虽然这些增量几乎是相同的,但关键的区别在于相邻的增量没有公共因子。使用Hibbard增量时希尔排序的最坏情形运行时间为O(N^(3/2))。Sedgewick提出了几种增量序列,其最坏情形运行时间达到O(N^(4/3)),经验研究指出,在实践中这些序列的运行要比Hibbard的好得多,其中最好的序列是{1,5,19,41,109,…},该序列中的项或者是9*4^i — 9*2^ i + 1, 或者是4^i — 3*2^ i + 1。通过将这些值按顺序放到一个数组中可以最容易地实现该算法。(摘自《数据结构与算法分析---c语言描述》,Mark Allen Weiss著)
补充一个Hibbard增量的希尔排序法:
template <class T>
void ShellSort(T a[], int len)//Hibbard增量序列1,3,7,…,2^k - 1
{
int k = 0;
for (int n=len; n>3; n>>=1)
++k;
int increase = (1 << k) - 1;//求出最大的增量值2^k - 1
for (; increase>0; increase/=2)
{
for (int i=increase; i<len; i++)
{
T temp = a[i];
int j = i;
for (; j>=increase; j-=increase)//元素后移
{
if (temp < a[j-increase])
a[j] = a[j-increase];
else
break;
}
a[j] = temp; //插入
}//for
}//for
}
7 楼
bpttc [专家分:8790] 发布于 2007-04-24 13:33:00
template <class T>
void InsertSort(T a[], int len)
{
int i, j;
for (i=1; i<len; i++)
{
a[0] = a[i];
for (j=i-1; a[j]>temp; j--)
a[j+1] = a[j];
a[j+1] = a[0];
}
}
for (j=i-1; a[j]>temp; j--) 中的temp忘记改成a[0]了
8 楼
bpttc [专家分:8790] 发布于 2007-04-24 16:26:00
void Two_wayInsertionSort( int A[], int N )
{
int* D = ( int* )malloc( ( N << 1 ) * sizeof( int ) );
int first = N;
int final = N;
int P, i;
int temp;
D[N] = A[0];
for ( P = 1; P < N; ++P )
{
temp = A[P];
if ( temp > D[N] )
{
for ( i = ++final; i > N && temp < D[i-1]; --i )
{
D[i] = D[i-1];
}
D[i] = temp;
}
else
{
for ( i = --first; i < N && temp > D[i+1]; ++i )
{
D[i] = D[i+1];
}
D[i] = temp;
}
}
for ( i = 0; i < N; ++i, ++first )
{
A[i] = D[first];
}
free(D);
return;
}
写了个二路排序,辅助向量用了2N个空间
9 楼
bpttc [专家分:8790] 发布于 2007-05-31 12:46:00
sedgewick[] =
{
1,
5,
19,
41,
109,
209,
505,
929,
2161,
3905,
8929,
16001,
36289,
64769,
146305,
260609,
587521,
1045505,
2354689,
4188161,
9427969,
16764929,
37730305,
67084289,
150958081,
268386305,
603906049,
1073643521
};
sedgewick[] =
{
1073643521,
603906049,
268386305,
150958081,
67084289,
37730305,
16764929,
9427969,
4188161,
2354689,
1045505,
587521,
260609,
146305,
64769,
36289,
16001,
8929,
3905,
2161,
929,
505,
209,
109,
41,
19,
5,
1
};
补充一个增量序列
10 楼
fishion [专家分:10] 发布于 2007-06-01 08:53:00
挺好的,支持
我来回复