1. 程式人生 > >直接插入排序和希爾排序

直接插入排序和希爾排序

插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料。

直接插入排序:每次將一個待排序的元素,與已排序的元素從尾到頭進行比較,找到合適位置進行插入;


對一個亂序陣列進行排序,將第一個元素看作是有序陣列,後面的元素是待插入元素,進行直接插入排序,在這個有序陣列的基礎上插入後面的資料,直到所有資料全部直接插入排序完成。

void SortInsert(int *arr, int length)
{
	assert(arr);
	if (length <= 1)   //陣列只有一個元素不需要排序
	{
		return;
	}
	int index = 0;
	while (index < length - 1)
	{
		int end = index;
		int x = arr[end + 1];
		for (int i = end; end >= 0;)
		{
			if (arr[end] > x)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}

		//break,出來 x插入在end的下一個位置
		//for迴圈走完出來,此時end = -1;x插入在0這個位置,也就是end+1這個位置;
		arr[end + 1] = x;
		index++;
	}
}
演算法分析:將陣列排序成升序的前提下討論。

1.當陣列所有(n個數據)元素為升序排列時,也就是此時陣列有序,僅外迴圈迴圈n-1次,裡邊的for迴圈均只走了一次;此時的時間複雜度為O(N)

2.當陣列所有元素為降序排列時,每一次外迴圈,待插入元素都要和index之前的元素進行比較,並且後移index次。此時的時間複雜度為:1+ 2+3+4+5+6+...+(n-1) = n*(n-1)/2 = O(N*N)

希爾排序:

是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序,隨著增量逐漸減小,分組越來越多,當增量減少至1時,排序完成。

大致分為兩步完成;

第一步,預排序:使整個陣列接近有序,大的資料儘快到後面,小的資料儘快到前面;

第二部,最後排序:此時gap = 1;也就是分組的增量為1,就是直接插入排序;

如果我們有這樣一些資料,{2,5,4,9,3,6,8,7,1,0}對其進行一趟希爾排序


進行多趟排序,直至gap = 1時直接插入排序完成,所有的才算正式結束。

程式碼實現:

void SortShell(int arr[], int length)
{
	assert(arr);
	int gap = length;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < length - gap; i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end] > tmp)
				{  
					arr[end + gap] = arr[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}

}
演算法分析:

增量:gap

演算法最開始以一定的gap進行排序,然後會繼續以一定gap進行排序,最終演算法以gap為1進行排序。當gap=1時,演算法為直接插入排序,這就保證了資料一定會被排序。

希爾排序的時間複雜度與增量序列的選取有關;