1. 程式人生 > >【排序演算法3】希爾排序

【排序演算法3】希爾排序

此篇我是17年7月份有幸閱讀到MoreWindows的此篇部落格 希爾排序 可惜的是當時不是很懂。又因工作繁忙以至於忘了此事。直到最近換完工作才有想起有此坑還未填上,便又翻出看了一遍。這次有了全新的認識。特此記錄

現在才想起當時為何看的不是很懂,是因為此篇部落格中的實驗中間省略了一小部分。看似省略的這一小部分,卻讓我當時深深疑惑。還好現在已經按照部落格中的意思將內容補細緻一些。下面的程式碼註釋部分,有我當時寫程式碼是的錯誤思路及反思。

#include <stdio.h>
#include <Windows.h>


/*
	希爾排序的實質是分組插入排序,又稱縮小增量排序。

基本思想:
	先將整個待排元素序列分割成若干子序列(由相隔某個“增量”的元素組成)分別進行直接插入排序,然後依次縮減增量再排序
	待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次!!!直接插入排序。因為直接插入排序在元素基本有序的情況下效率是很高的


實驗:
	n = 10的一個數組  49,38,65,97,26,13,27,49,55,4

第一次gap = 10 / 2 = 5
49	38	65	97	26	13	27	49	55	4
1a					1b
	2a					2b
		3a					3b				註解:數字相同為同一組,同一組用字母表示是該組的第幾個元素
			4a					4b
				5a					5b
第一次排序完成之後
13	27	49	55	4	49	38	65	97	26

第二次gap = 5 / 2 = 2
13	27	49	55	4	49	38	65	97	26
1a		1b		1c		1d		1e
	2a		2b		2c		2d		2e
第二次排序完成之後
4	26	13	27	38	49	49	55	97	65

第三次gap = 2 / 2 = 1
4	26	13	27	38	49	49	55	97	65
1a	1b	1c	1d	1e	1f	1g	1h	1i	1j
第三次排序完成之後
4	13	26	27	38	49	49	55	65	97
*/

void Swap(int *,int *);

void shell_sort(int a[],int n)
{
	int gap,i,j,k,p,temp;
	for( gap = n / 2 ; gap > 0 ; gap /= 2 )
	{
		//每一次gap都是直接插入排序
		for( i = 0 ; i < gap ; ++i )
		{
			//直接插入排序
			for( j = i + gap ; j < n ; j += gap )
			{
				for( k = j - gap ; k >= 0 ; k -= gap)
				{
					if( a[k] < a[j] )
					{
						break;
					}
				}
				if( k != j - gap )
				{
					temp = a[j];
					for( p = j - gap ; p > k ; p -= gap)
					{
						a[p + gap] = a[p];
					}
					a[p + gap] = temp;
				}
			}
		}
	}
}

//優化上面變數太多,優化一下
void shell_sort2(int a[],int n)
{
	int gap,i,j,temp;
	for( gap = n / 2 ; gap > 0 ; gap /= 2 )
	{
		//每一次gap都是直接插入排序
		for( i = 0 ; i < gap ; ++i )
		{
			//temp = a[i];
			for( j = i + gap ; j < n ; j += gap )
			{
				//不能直接2個相鄰的資料交換,或者說交換之後還得繼續檢視與下個數據的對比情況應該要用覆蓋的方法
				//if( a[j] < a[j - gap] )
				//{
				//	Swap( &a[j],&a[j-gap] );
				//}
				//else
				//{
				//	break;
				//}
				if( a[j] < a[j - gap] )
				{	
					//先不換資料
					//temp = a[j - gap];
					//a[j - gap] = a[j];
					//記錄下這個較小值,安排到合適的位置
					temp = a[j];
					int k = j - gap;
					while( k >= 0 && a[k] > temp)  //這個k>=0 很有可能會安排到最前面 k == 0 的情況
					{
						//往後移  因為前面的資料已經是有序的了,後移覆蓋就行
						a[k + gap] = a[k];
						k -= gap;
					}
					a[k + gap] = temp;
				}
			}
		}
	}
}

void Swap(int *a , int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}


void print(int a[],int n)
{
	int i;
	for( i = 0 ; i < n ; ++i )
	{
		printf("%d ",a[i]);
	}
	printf("\n");
}

int main()
{
	int a[10] = {49,38,65,97,26,13,27,49,55,4};
	shell_sort2(a,10);
	print(a,10);
	system("pause");
	return 0;
}