排序

排序


一、插入排序

1.直接插入排序

時間複雜度O(N^2)

思想:每次用無序區的第一個元素和有序區的元素從後往前比,找到合適的位置後,把有序區的元素依次後移,插入那個元素後使有序區再次有序

<span style="font-size:18px;">void InsertSort(int *a,int length)
{
	for (int i = 0; i < length-1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end>=0&&tmp < a[end])
		{
			a[end + 1] = a[end];
			end--;
		}
		a[end + 1] = tmp;
	}
}</span>
對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

第一次:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

第二次:0, 3,7, 5, 4, 8, 1, 9, 2, 6

第三次:0, 3, 5, 7, 4, 8, 1, 9, 2, 6

第四次:0, 3, 4, 5, 7, 8, 1, 9, 2, 6

...
2.希爾排序

時間複雜度在O(N^1.25)左右

由於直接插入排序在相對有序的情況下事效率比較高,最壞的情況就是相對逆序的情況,希爾排序是插入排序的優化,先進行預排序,設置一個gap,慢慢縮小gap的範圍,達到其相對有序。

void ShellSort(int *a,int length)
{
	assert(a);
	int gap = length;
	while (gap > 1)
	{
		gap = gap / 3 + 1;//慢慢縮小範圍直到縮小到1
		for (int i = 0; i < length-gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (a[end]>tmp&&end>=0)
			{
				a[end + gap] = a[end];
				end -= gap;
			}
			a[end + gap] = tmp;
		}
	}
}

對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

第一次(gap=4):0, 6, 1, 5, 2, 7, 3, 9, 4, 8

第二次(gap=2) :0, 5,1, 6, 2, 7, 3, 8, 4, 9

第三次(gap=1):0, 1,  2, 3, 4, 5, 6, 7, 8, 9

二、選擇排序

1.直接選擇排序

時間複雜度:O(N^2)

思想:遍歷選出這組數中最大的,和最後一個數做交換

void SelectSort(int *a,int length)
{
	
	int end = length - 1;
	for (; end > 0; end--)
	{
		int MaxIndex = 0;
		for (int i = 0; i <= end; i++)//選出最大值的下標
		{
			if (a[MaxIndex] < a[i])
				MaxIndex = i;
		}
		swap(a[end], a[MaxIndex]);//交換到相對最後的位置
	}
}

對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

第一次:0, 7, 3, 5, 4, 8, 1,6, 2, 9

第二次:0, 7, 3, 5, 4,2, 1, 6, 8, 9

第三次:0,6, 3, 5, 4, 2, 1,7, 8, 9

第四次:0, 1, 3, 5, 4, 2,6, 7, 8, 9

……


-->優化

遍歷時可以選出最大和最小的值的下標,將最小的放到相對頭的位置,最大的放到相對尾的位置

void SelectSort(int *a, int length)
{
	assert(a);
	assert(length > 0);

	int end = length - 1;
	int start = 0;
	while (end > start)
	{
		int iMax = start;
		int iMin = start;
		for (int i = start+1; i <= end; i++)
		{
			if (a[i] >= a[iMax])
				iMax = i;
			if (a[i] < a[iMin])
				iMin = i;
		}
		if ((start != iMax)&&(end != iMin))//情況1
		{
			swap(a[start], a[iMin]);
			swap(a[end], a[iMax]);
		}
		if ((start == iMax)&&(end == iMin))//情況2
		{
			swap(a[iMax], a[iMin]);
		}
		if ((start == iMax)&&(end != iMin))//情況3
		{
			swap(a[iMax], a[end]);
			swap(a[iMin], a[start]);
		}
		if ((start != iMax) && (end == iMin))//情況4
		{
			swap(a[iMin], a[start]);
			swap(a[iMax], a[end]);
		}
		start++;
		end--;
		
	}
}

對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

第一次:0, 7, 3, 5, 4, 8, 1, 6, 2, 9

第二次:0, 1, 3, 5, 4, 2, 7, 6, 8, 9

第三次:0, 1, 2, 5, 4, 3, 6, 7, 8, 9

第四次:0, 1, 2, 3, 4, 56, 7, 8, 9

……

2.堆排序

時間複雜度:O(N *logN)

利用堆的性質,先建一個大堆,使堆頂存放最大的元素,再依次用堆頂元素和相對最後的一個元素交換,從而把最大的排到後面,每交換一次,均需要把剩下的元素向下調整一次

void _AdjustDown(int *a, int size, int parent)//向下調整
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		if (a[child] < a[child + 1]&&(child+1 < size))
		{
			child++;
		}
		if (a[child]>a[parent])
		{
			swap(a[child], a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
void HeapSort(int *a, int length)
{
	for (int i = (length-2)/2; i >=0 ; i--)//建堆
	{
		_AdjustDown(a, length, i);
	}
	for (int i = 0; i < length; i++)//排序
	{
		swap(a[0], a[length - 1 - i]);
		_AdjustDown(a, length-i-1, 0);
	}
}

對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

建堆:9, 7, 8, 5, 6, 3, 1, 0, 2, 4

堆排序:第一次:8, 7, 4, 5, 6, 3, 1, 0, 2, 9

      第二次:7, 6, 4, 5, 2, 3 , 1 ,0,8,9

……

三、交換排序

1.冒泡排序

時間複雜度:O(N^2)

void BubbleSort(int *a, int length)
{
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length -1- i;j++)
		{
			if (a[j]>a[j + 1])
				swap(a[j], a[j + 1]);
		}
	}
}
對於:0, 7, 3, 5, 4, 8, 1, 9, 2, 6

i=0:  0, 3, 5, 4, 7, 1, 8, 2, 6, 9

i=1:     0, 3, 4, 5, 1, 7, 2, 6, 8, 9

i=2:     0, 3, 4, 1, 5, 2, 6 ,7 ,8, 9

在它有序時它任然會循環,時間效率低,故設置一個值來判斷它在循環的過程中是否發生交換,若沒有發生循環,直接退出循環

-->優化

void BubbleSort(int *a, int length)
{
	bool exchange = false;
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length - 1 - i; j++)
		{
			if (a[j]>a[j + 1])
			{
				swap(a[j], a[j + 1]);
				exchange = true;
			}
		}
		if (exchange == false)//若沒有發生交換說明已經有序
			break;
	}
}

2.快速排序

int partition(int *a, int left, int right)
{
	int key = a[right];
	int begin = left;
	int end = right - 1;
	while (begin < end)
	{
		while (a[begin] < key)
		{
			++begin;
		}
		while (begin < end&&a[end]>key)
		{
			--end;
		}
		if (begin < end)
		{
			swap(a[begin], a[end]);
		}
	}
	if (a[begin]>a[right])
	{
		swap(a[begin], a[right]);
		return begin;
	}
	else
		return right;
}
void QuickSort(int *a, int left,int right)
{
	assert(a);
	if (left < right)
	{
		int div = partition(a, 0, right);
		QuickSort(a, 0, div - 1);
		QuickSort(a, div + 1, right);
	}
}



發佈了28 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章