插入排序 希尔排序 C++

最优时间复杂度为o(n),又称缩小增量排序。

逻辑分析:

1、希尔排序首先是确定增量,默认的希尔增量(不一定是最优)为length/2。

2、根据增量分组,将分组的元素利用直接插入法排序。

3、增量=增量/2,再次分组,一直到增量为1为止。

    通过上述步骤我们可以知道,代码会有3个循环,第一个gap的更新,即for(int gap=len/2;gap>0;gap/=2)。第二个和第三个循环是对分组数组进行直接插入排序。

代码分析:

 数组a[] = { 2,1,4,5,3,8,7,9,0,6 },length=10。

第一次大循环

gap=length/2=5,i=5,j=i-gap=0,a[j]=2<a[j+gap]=8,此时数组不做任何操作。

gap=length/2=5,i=6,j=i-gap=1,a[j]=1<a[j+gap]=7,此时数组不做任何操作。

gap=length/2=5,i=7,j=i-gap=2,a[j]=4<a[j+gap]=9,此时数组不做任何操作。

gap=length/2=5,i=8,j=i-gap=3,a[j]=5<a[j+gap]=0,故交换a[j]和a[j+gap],数组a[]= { 2,1,4,0,3,8,7,9,5,6 }。

gap=length/2=5,i=9,j=i-gap=4,a[j]=3<a[j+gap]=6,此时数组不做任何操作。

第二次大循环

gap=gap/2=2,i=2,j=i-gap=0,a[j]=3<a[j+gap]=4,此时数组不做任何操作。

gap=gap/2=2,i=3,j=i-gap=1,a[j]=1>a[j+gap]=0,故交换a[j]和a[j+gap],数组a[]= { 2,0,4,1,3,8,7,9,5,6 }。

gap=gap/2=2,i=4,j=i-gap=2,a[j]=4>a[j+gap]=3,故交换a[j]和a[j+gap],数组a[]= { 2,0,3,1,4,8,7,9,5,6 }。

gap=gap/2=2,i=4,j=i-gap=0,a[j]=2<a[j+gap]=3,此时数组不做任何操作。

gap=gap/2=2,i=5,j=i-gap=3,a[j]=1<a[j+gap]=8,此时数组不做任何操作。

gap=gap/2=2,i=6,j=i-gap=4,a[j]=4<a[j+gap]=7,此时数组不做任何操作。

gap=gap/2=2,i=7,j=i-gap=5,a[j]=8<a[j+gap]=9,此时数组不做任何操作。

gap=gap/2=2,i=8,j=i-gap=6,a[j]=7>a[j+gap]=5,故交换a[j]和a[j+gap],数组a[]= { 2,0,3,1,4,8,5,9,7,6 }。

gap=gap/2=2,i=9,j=i-gap=7,a[j]=9>a[j+gap]=6,故交换a[j]和a[j+gap],数组a[]= { 2,0,3,1,4,8,5,6,7,9 }。

第三次大循环

gap=gap/2=1,i=1,j=i-gap=0,a[j]=2>a[j+gap]=0,故交换a[j]和a[j+gap],数组a[]= { 0,2,3,1,4,8,5,6,7,9 }。

gap=gap/2=1,i=2,j=i-gap=1,a[j]=2<a[j+gap]=3,此时数组不做任何操作。

gap=gap/2=1,i=3,j=i-gap=2,a[j]=3>a[j+gap]=1,故交换a[j]和a[j+gap],数组a[]= { 0,2,1,3,4,8,5,6,7,9 }。

gap=gap/2=1,i=3,j=j-gap=1,a[j]=2>a[j+gap]=1,故交换a[j]和a[j+gap],数组a[]= { 0,1,2,3,4,8,5,6,7,9 }。

gap=gap/2=1,i=3,j=j-gap=0,a[j]=0<a[j+gap]=1,此时数组不做任何操作。

gap=gap/2=1,i=4,j=i-gap=3,a[j]=3<a[j+gap]=4,此时数组不做任何操作。

gap=gap/2=1,i=5,j=i-gap=4,a[j]=4<a[j+gap]=8,此时数组不做任何操作。

gap=gap/2=1,i=6,j=i-gap=5,a[j]=8>a[j+gap]=5,故交换a[j]和a[j+gap],数组a[]= { 0,1,2,3,4,5,8,6,7,9 }。

gap=gap/2=1,i=6,j=j-gap=4,a[j]=4<a[j+gap]=5,此时数组不做任何操作。

gap=gap/2=1,i=7,j=i-gap=6,a[j]=8>a[j+gap]=6,故交换a[j]和a[j+gap],数组a[]= { 0,1,2,3,4,5,6,8,7,9 }。

gap=gap/2=1,i=7,j=j-gap=5,a[j]=5<a[j+gap]=6,此时数组不做任何操作。

gap=gap/2=1,i=8,j=i-gap=7,a[j]=8>a[j+gap]=7,故交换a[j]和a[j+gap],数组a[]= { 0,1,2,3,4,5,6,7,8,9 }。

gap=gap/2=1,i=8,j=j-gap=6,a[j]=6<a[j+gap]=7,此时数组不做任何操作。

gap=gap/2=1,i=9,j=i-gap=8a[j]=8<a[j+gap]=9,此时数组不做任何操作。

排序完成,输出数组a[]= { 0,1,2,3,4,5,6,7,8,9 }。

#include<iostream>
#include<cstdlib>

using namespace std;

//交换
void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}


//希尔排序,首先根据增量分组,然后对分组元素进行直接插入排序
void shellSort(int a[],  int length)
{
	for (int gap = length/2; gap>0; gap/=2)
	{
		for (int i = gap; i<length;++i)

		{
			for (int j = i - gap; j >=0 && a[j] > a[j + gap]; j -= gap)
			{
				swap(a[j], a[j + gap]);
			}
		}
	}

}

int main()
{
	int a[] = { 2,1,4,5,3,8,7,9,0,6 };

	shellSort(a, 10);

	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << "";

	}
	cout << endl;
	system("pause");
	return 0;

}

发现上述代码真的有好多重复的地方,加了一个标志,来改进一下

#include<iostream>
#include<cstdlib>

using namespace std;

void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}



void shellSort(int a[],  int length)
{
	
	for (int gap = length/2; gap>0; gap/=2)
	{
		for (int i = gap; i<length;++i)

		{
			bool action = true;
			for (int j = i - gap; j >=0 && action; j -= gap)
			{
				if (a[j] > a[j + gap])
				{
					swap(a[j], a[j + gap]);
				}
				else  action = false;
				
				
			}
		}
	}

}

int main()
{
	int a[] = { 65,44,77,5,24,89,72,58,40,69 };

	shellSort(a, 10);

	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << " ";

	}
	cout << endl;
	system("pause");
	return 0;

}

猜你喜欢

转载自blog.csdn.net/summerlq/article/details/81216258
今日推荐