数据结构 排序2 插入排序
插入排序:该排序是把序列中的值插入一个已经排好的序列中,直到序列的结束。
a.直接插入排序:该排序是对冒泡排序的改进,它比冒泡排序快2倍。一般不用在数据大于1000的场合下使用插入排序,或者重复排序超过200数据项的序列。
详细请见代码:
- #include <stdio.h>
- #include <stdlib.h>
- #define NUM 50
- //插入排序算法
- /*该算法过程如下:
- 如数组{ 4,3,1 }
- 第一轮循环:4和3比较,4>3,先把4赋值到3的位置,变成{ 4,4,1}
- while循环退出,把3赋值到第一个4的位置,变成{ 3, 4, 1}
- 第二轮循环:4和1比较,4>1,4赋值到1的位置,变成{ 3,4,4 }
- 继续while循环,3>1,3赋值到第一4的位置,变成{ 3,3,4 }
- while循环退出,把1赋值到第一个3的位置,变成{ 1,3,4 }
- 自此完成插入排序。
- */
- int InsertSort( int a[], int n )
- {
- int i, j, t;
- for( i = 1; i < n; i++ )
- {
- t = a[i];
- j = i;
- while( ( j > 0 ) && ( t < a[j-1] ) )
- {
- a[j] = a[j-1];
- j--;
- }
- a[j] = t;
- }
- return 1;
- }
- int main( void )
- {
- //int a[NUM] = { 3, 4, 2, 5, 1 };
- int i;
- int a[NUM];
- for( i = 0; i < NUM; i++ )
- {
- a[i] = rand() % NUM;
- }
- //插入排序
- InsertSort( a, NUM );
- for( i = 0; i < NUM; i++ )
- {
- printf( "%d \n", a[i] );
- }
- return 0;
- }
b.希尔排序( shell sort ):sheell排序通过将数据分成不同的组,先对每一组排序进行排序,然后再对所有的元素进行一次插入排序,以减少数据交换和移动的次数。平均效率是O( nlogn )。其中分组的大小对算法产生重要影响。现在多用D.E.Knuth分组方法。
Shell排序比冒泡排序快5倍,比插入排序大致快2倍。Shell排序比起QuickSort,MergeSort(归并排序),HeapSort慢很多。但是它的实现比较简单,它适合于数据量在5k以下并且速度并不是特并重要的场合。它对于数据量较小的数列重复排序是非常好的。
详细请见代码:
- #include <stdio.h>
- #include <stdlib.h>
- #define NUM 50
- //希尔排序
- //希尔排序是将数据分成若干组的插入排序
- //其原理可以用三步曲来解释:
- //1.插入排序中如果前面已经排好序,再插入一个新的数据是不是很快呀!
- //2.既然很快,为什么不事先排好序。
- //3.
- //算法实例:如数组{ 2,4,3, 1,3,6, 0,2,8 }
- /*先三分组2,4,3; 1,3,6; 5,2,8;
- 第一轮比较:2,4,3与1,3,6对应位置交换后1,3,3; 5,4,6
- 第二轮比较:首先2,4,6的2和5,2,8的5比较,如果5比2小就会交换位置
- 这时还会和1,3,3中的1比较,如果5比1还小,它们交换位置。同理对于
- 其他位的数据做同样的比较。
- 其最后看到的结果是:每段的所有对应位的数是按顺序排列的,
- 同一段的所有数不一定按顺序排列。
- Shell排序最后的分段大小必须为1.
- */
- int Shell2DividSort( int a[], int n )
- {
- //2分法希尔排序
- int i, j, t, s;
- for( s = n / 2; s > 0; s /= 2 ) //2分法希尔排序
- {
- for( i = s; i < n; i++ )
- {
- for( j = i - s; j >= 0; j -= s )
- {
- if( a[j] > a[j+s] ) //相邻的两个段的对应位做比较
- {
- t = a[j];
- a[j] = a[j+s];
- a[j+s] = t;
- }
- }
- }
- }
- return 1;
- }
- int main( void )
- {
- // int a[NUM] = { 3, 4, 2, 5, 1 };
- int i;
- int a[NUM];
- for( i = 0; i < NUM; i++ )
- {
- a[i] = rand() % NUM;
- }
- //2分法希尔排序
- Shell2DividSort( a, NUM );
- for( i = 0; i < NUM; i++ )
- {
- printf( "%d \n", a[i] );
- }
- return 0;
- }
- #include <stdio.h>
- #include <stdlib.h>
- #define NUM 100
- //希尔排序
- //希尔排序是将数据分成若干组的插入排序
- /*
- 希尔排序原来已经知道,就是把数据分组。
- 然而分成不同大小的组,对数据排序时间有不同影响。
- 如数组( a=2,b=1,c=3,d=1 )这样的数组,如果二分法的话,
- 排完的结果是( a=2, d=1; c=3, b=1 )这样没有什么变化。
- 这样的数据其实并不少见,那怎么尽可能避免,让数据分组最大化
- 的起到调整作用呢?目前公认的方式采用特定数作分组大小。
- 至于怎么推导出来的,暂不作考证!
- */
- int ShellSort( int a[], int n )
- {
- //特定数组希尔排序
- int i, j, t;
- int *s, ss;
- int size[] = { // 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, 0
- }; //这个数据有两个特定公式算出来的。
- for( s = size; *s > n; s++ )
- {
- ; //找到比分段的值比n还小时,确定其地址位置
- }
- for( ; *s > 0; s++ ) //特定数组希尔排序
- {
- ss = *s;
- for( i = ss; i < n; i++ )
- {
- for( j = i - ss; j >= 0; j -= ss )
- {
- if( a[j] > a[j+ss] ) //相邻的两个段的对应位做比较
- {
- t = a[j];
- a[j] = a[j+ss];
- a[j+ss] = t;
- }
- }
- }
- }
- return 1;
- }
- int main( void )
- {
- // int a[NUM] = { 3, 4, 2, 5, 1 };
- int i;
- int a[NUM];
- for( i = 0; i < NUM; i++ )
- {
- a[i] = rand() % NUM;
- }
- //特定数组希尔排序
- ShellSort( a, NUM );
- for( i = 0; i < NUM; i++ )
- {
- printf( "%d \n", a[i] );
- }
- return 0;
- }
浙公网安备 33010602011771号