原理:
通过减少复杂度来提高效率,利用一个“增量(可以是任意数)”来构成一个增量序列,进而实现数组中的数据进行跳跃式比较,从而减少普通排序中反复比较的次数。
#include <stdio.h>
#include "sort.h"//这里我自己写的头文件
//顺序表的shell排序
void shell_sort(sqlist *sq)
{
int increment = 0;
increment = sq->length;//初始化一个增量
int i,j;
do{
increment = increment/3 + 1;//增量序列(increment/3可根据数据的大小适当调整)
for(i = increment+1;i <= sq->length;i++)//从增量的数据开始遍历后面的每一个数据
{
if(sq->data[i] < sq->data[i-increment])//将数组中的数据跳跃式比较
{
sq->data[0] = sq->data[i];//规定数据中的第一个元素不存数据,作为中间变量
for(j = i-increment;j > 0 && sq->data[j] > sq->data[0];j -= increment)
{
sq->data[j+increment] = sq->data[j];
}
sq->data[j+increment] = sq->data[0];
}//该if语句实现两个数据的交换
}
}while(increment > 1);//这里最后一次结束要让increment=1
}
以上代码举例:
1.传入数组arr[10] = {0, 81, 98, 14, 70, 3, 81, 19, 59, 5}(我们规定0号元素不存数据作为中间值,暂存为0),其中length = 9。
2.进入该函数中,increment初始值为9,这时第一次进入do循环。
3.increment = 4,进入for循环中,(i=5;i<=9;i++)相当于从5开始遍历数组到末尾,
4,进入for循环后开始比较,arr[5]=3 < arr[1]=81----交换;arr[6]=81 < arr[2]=98----交换;arr[7]=19 > arr[3]=14----不交换;arr[8]=59 < arr[4]=70----交换;arr[9]=5 < arr[5]=81----交换。第一次循环结束,此时arr[10] = {0,3,81,14,59,5,98,19,70,81}。
5,increment=4>1,第二次进入do循环,increment=2,进入for循环,i=3,即arr[3]=14 > arr[1]=3----不交换;arr[4]=59 < arr[2]=81----交换;arr[5]=5 < arr[3]=14----交换;arr[6]=98 > arr[4]=81----不交换;arr[7]=19 > arr[5]=14----不交换;arr[8]=70 < arr[6]=98----交换;arr[6]=70 < arr[4]=81----交换;arr[9]=81 > arr[7]=19----不交换。此时arr[10]={0,3,59,5,70,14,81,19,98,81}。
6,increment=2>1,第三次进入do循环,increment=1,进入for循环,i=2,即arr[2]=59 > arr[1]=3----不交换;arr[3]=5 < arr[2]=59----交换;arr[4]=70 > arr[3]=59----不交换;arr[5]=14 > arr[4]=70----交换;arr[4]=14 > arr[3]=59----交换;arr[6]=81 > arr[5]=70----不交换;arr[7]=19 < arr[6]=81----交换;arr[6]=19 > arr[5]=70----交换;arr[5]=19 > arr[4]=59----交换;arr[9]=81 < arr[8]=98----交换。
此时arr[10]={0,3,5,14,19,59,70,81,81,98}.
7,increment=1,结束循环。
代码结果: