常见排序算法的整理

一直以来对排序算法没有深刻的理解,只能简单的代码编写,因此今天抽出一些时间对以前排序的不足加以修改。

这里我们来探讨一下常用的比较排序算法,下表给出了常见比较排序算法的性能:

稳定性的判别:如果说排序前两个相等的数位置是a,b,排序后两个数仍然是a,b,则说明这个排序是稳定的。通俗来讲就是说:排序前后两个相等的数相对位置不发生改变。

冒泡排序:

1.比较相邻的元素,如果前者大于后者,则将两个数进行交换。

2.对每一对相邻元素都做相同的工作,从第一对到最后一对,这步做完之后,最后一个元素便是最大值。

3.针对所有元素都重复以上步骤,每重复一次,便对相邻比较次数减一。

4.直到没有相邻元素比较即完成了冒泡排序。

代码实现:

//冒泡排序
//时间复杂度O(N^2)
//空间复杂度O(1)
//稳定性:稳定
void BubbleSort(int array[], int size)
{
	int i, j;
	for (i = 0; i < size-1; i++)
	{
		for (j = 0; j < size - 1 - i; j++)
		{
			if (array[j] > array[j + 1])
				swap(&array[j], &array[j + 1]);
		}
	}
}

选择排序:

1.从第一个元素开始,然后与所有元素进行比较。

2.遇到比他小的进行交换,一直比较完所有元素,得到最小的那个元素。

3.除了最小的那个元素,其余重复以上步骤,直到只剩一个元素为止。

代码实现:

//选择排序
//时间复杂度O(n^2)
//空间复杂度O(1)
//稳定性:不稳定
void SelectSort(int array[], int size)
{
	int i = 0;
	for (; i < size; i++)
	{
		for (int j = i; j < size; j++)
		{
			if (array[i]<array[j])
			{
				swap(&array[i], &array[j]);
			}
		}
	}
}

插入排序:

1.首先默认第一个元素已经排好序,然后取出下一个元素。

2.将排好序的元素进行从后往前遍历,如果说已排序的元素大于新元素,则进行搬运,将该元素移到下一位置。

3.继续遍历,直到元素小于新元素时,将新元素插入到元素后面。

4.重复以上步骤。直到所有元素比较完成。

代码实现:

//插入排序
//时间复杂度O(N^2)
//空间复杂度O(1)
//稳定性:稳定
void InsertSort(int array[], int size)
{
	if (size <= 1)
		return;
	int bound = 1;//[0,bound)有序空间
	for (; bound < size; bound++)
	{
		int bound_value = array[bound];
		int i = bound;
		for (; i>0; i--)
		{
			if (array[i - 1] < bound_value)
			{
				array[i] = array[i - 1];//进行搬运
			}
			else{
				break;
			}
		}
		array[i] = bound_value;
	}
}

堆排序:

1.用给定的无序数组建一个大堆。

2.每次将堆顶元素与最后一个数进行交换。

3.将堆的大小减一,进行重新调整,直到只剩一个元素。

代码实现:

//堆排序
//时间复杂度O(nlogn)
//空间复杂度O(1)
//稳定性:不稳定
void AdjustDown(int array[], int size, int index)//向下调整,大堆
{
	int parent = index;
	int child = 2 * index + 1;
	while (child < size){
		if (child + 1 < size&&array[child] < array[child + 1])
		{
			child = child + 1;
		}
		if (array[parent]<array[child])
		{
			swap(&array[parent], &array[child]);
		}
		else{
			break;
		}
		parent = child;
		child = 2 * child + 1;
	}
	return;
}
void HeapCreate(int array, int size)
{
	if (size <= 1)
		return;
	int i = (size - 1 - 1) / 2;
	for (; i >= 0; i--)
	{
		AdjustDown(array, size, i);
	}
}
void HeapPop(int array[], int size)
{
	if (size <= 1)
		return;
	swap(&array[0], &array[size - 1]);
	AdjustDown(array, size-1,0);
}
void HeapSort(int array[], int size)
{
	if (size <= 1)
		return;
	HeapCreate(array, size);

	int i = 0;
	for (; i < size; i++)
	{
		HeapPop(array, size - i);
	}
}

归并排序:

1.申请同等大小的空间,将数组拆分为一小块连续的空间(其实也就是拆成1)。

2.设置两个指针,最初为止为两个已排好序数组的起始位置。

3.比较两个指针所指向的内容,将较小的元素放入到新的空间当中,并且指针向后移动。

4.重复3,直到有一指针指向排好序的末尾。

5.将另一数组剩余的元素全都放入新数组当中。

代码实现:

//归并排序
//时间复杂度O(nlogn)
//空间复杂度O(N)
//稳定性:稳定
void MergeArray(int array[], int beg, int mid, int end, int *tmp)
{
	int output = beg;
	int cur1 = beg;
	int cur2 = mid;
	while (cur1 < mid&&cur2 < end)
	{
		if (array[cur1] < array[cur2])
		{
			tmp[output++] = array[cur1++];//将较小值放入新空间
		}
		else{
			tmp[output++] = array[cur2++];
		}
	}
	while (cur1 < mid)
	{
		tmp[output++] = array[cur1++];
	}
	while (cur2 < end)
	{
		tmp[output++] = array[cur2++];
	}
	memcpy(array + beg, tmp + beg, sizeof(int)*(end - beg));//还给原空间
}
void _MergeSort(int array, int beg, int end, int *tmp)
{
	if (end - beg <= 1)
		return;
	int mid = beg + (end - beg) / 2;//分割
	_MergeSort(array, beg, mid, tmp);
	_MergeSort(array, mid, end, tmp);

	MergeArray(array, beg, mid, end, tmp);
}
void MergeSort(int array[], int size)
{
	int *tmp = (int *)malloc(sizeof(int)*size);//创建新空间
	_MergeSort(array, 0, size, tmp);
	free(tmp);
}

快速排序:

1.首先选一个元素,作为它的基准值。

2.定义两个指针,一个指向数组的起始,一个指向数组的末尾。

3.起始指针从前向后移动,找到第一个大于基准值的值,末尾指针从后往前走,找到第一个小于它的值。进行交换。

4.当两个指针交叉时,循环结束。交换起始指针指向的值和基准值的值。

5.返回基准值的下标。得到基准值前面的元素都比基准值小,后面的元素都比基准值大。

6.将基准值前面元素和后面元素进行分区重复以上步骤。

代码实现:

//快速排序
//时间复杂度O(nlogn)
//空间复杂度O(nlogn)
//稳定性:不稳定
int Partion(int array[], int beg, int end)
{
	int left = beg;
	int right = end - 1;
	int tmp = array[end - 1];//基准值
	while (left < right){
		while (left < right&&array[left] <= tmp)//找到第一个大于基准值的数
		{
			++left;
		}
		while (left<right&&array[right]>=tmp)//找到第一个小于基准值的数
		{
			--right;
		}
		if (left < right)
		{
			swap(&array[left], &array[right]);
		}
	}
	swap(&array[left], &array[end-1]);//将得到left左边都小于array[left],右边都大于array[left]
	return left;
}
void _QuickSort(int array[], int beg, int end)
{
	if (end - beg <= 1)
		return;
	int mid = Partion(array, beg, end);//分割空间
	_QuickSort(array, beg, mid);
	_QuickSort(array, mid, end);
}
void QuickSort(int array[], int size)
{
	_QuickSort(array, 0, size);
}
int main()
{
	int array[] = { 5, 7, 8, 9, 6, 2, 3, 1 };
	//BubbleSort(array, sizeof(array) / sizeof(array[0]));
	//SelectSort(array, sizeof(array) / sizeof(array[0]));
	//InsertSort(array, sizeof(array) / sizeof(array[0]));
	//HeapSort(array, sizeof(array) / sizeof(array[0]));
	//MergeSort(array, sizeof(array) / sizeof(array[0]));
	QuickSort(array, sizeof(array) / sizeof(array[0]));
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CDatreides/article/details/84185373