快速排序

快排

题目:

​ 快速排序。

分析:

​ 使用递归分治的方法,递归定义如下:
T ( n ) = { 1 ,    n = 1 T ( n − 1 ) + O ( n ) , n > 1 T(n) = \begin{cases} 1, \quad \quad \quad \quad \quad \quad \quad \space \space n=1 \\ T(n-1) + O(n), \quad n>1 \end{cases} T(n)={1,  n=1T(n1)+O(n),n>1
​ 平均时间复杂度:O(nlogn)

​ 最坏时间复杂度:O(n2)

​ 稳定性:不稳定

实现一:数据结构中的方法(王道)

1. **思想**

​ 选择一个 pivot 基准点(左端点),分别从右边和左边靠近。先从大的一端开始(右边),当右边小于 list[pivot] 时,将右边赋值给左边 list[left] = list[right] ;接着从左边靠近。当左边大于 list[pivot] 时,将左边赋值给右边 list[right] = list[left] 。往复循环,直至相遇。相遇点 left 即为 piovt 最终位置,将pivot放置在 list[left] ,形成左边都小于等于 list[pivot] ,右边都大于等于 list[pivot]pivot 处分成左右两块 (left, pivot - 1) (pivot + 1, right) 进行上述相同操作,直至分块长度小于1时,完成排序。

2. **代码**
#include <stdio.h>
/*
	稳定性:不稳定

	递归定义:
		  { 1				n=1
	T(n)={
		  { T(n-1) + O(n)	n>1

	平均时间复杂度:O(nlogn)

	最坏时间复杂度:O(n2)
*/

// 分区(数据结构中写法)
int partitionStruct(int list[], int left, int right) {
	int pivot = list[left];
	while (left < right) {
		while (left < right && list[right] >= pivot)
			right--;
		list[left] = list[right];
		while (left < right && list[left] <= pivot)
			left++;
		list[right] = list[left];
	}
	list[left] = pivot;
	return left;
}

// 快排
void quickSort(int list[], int left, int right) {
	if (left >= right) {
		return;
	}

    int pivot = partitionStruct(list, left, right);
	
	// 左边
	quickSort(list, left, pivot - 1);
	// 右边
	quickSort(list, pivot + 1, right);
}


void main() {
	int list[] = {2, 1, 7, 3, 5, 9};
	int length = sizeof(list) / sizeof(int);
	int i;
	quickSort(list, 0, length - 1);
	printf("规律分区\n");
	
	for (i = 0; i < length; i++) {
		printf("%d ", list[i]);
	}
}

实现二:算法设计与分析中的方法(王晓东-第五版)

  1. 思想

​ 选择一个 pivot 基准点(左端点),基准点索引为 p 分别从右边和左边靠近。先从大的一端开始(右边),当右边小于 list[pivot] 时,接着从左边靠近。当左边大于 list[pivot] 时,结束一轮循环,交换左右元素 swap(list, left, right) 。往复循环,直至相遇。将基准点和left位置的元素进行交换 swap(list, p, left) ,形成左边都小于等于 list[p] ,右边都大于等于 list[p]从pivot处分成左右两块 (left, pivot - 1) (pivot + 1, right) 进行上述相同操作,直至分块长度小于1时,完成排序。

  1. 代码
#include <stdio.h>
/*
	稳定性:不稳定

	递归定义:
		  { 1				n=1
	T(n)={
		  { T(n-1) + O(n)	n>1

	平均时间复杂度:O(nlogn)

	最坏时间复杂度:O(n2)
*/

// 交换
void swap(int list[], int left, int right) {
	int temp = list[right];
	list[right] = list[left];
	list[left] = temp;
}

// 分区(算法书中写法)
int partitionAlgorithm(int list[], int left, int right) {
	int pivot = list[left];
	int p = left;
	while (left < right) {
		while (left < right && list[right] >= pivot)
			right--;
		while (left < right && list[left] <= pivot)
			left++;
		swap(list, left, right);
	}
	swap(list, p, left);
	return right;
}

// 快排
void quickSort(int list[], int left, int right) {
	if (left >= right) {
		return;
	}
	int pivot = partitionAlgorithm(list, left, right);
	// 左边
	quickSort(list, left, pivot - 1);
	// 右边
	quickSort(list, pivot + 1, right);
}

void main() {
	int list[] = {2, 1, 7, 3, 5, 9};
	int length = sizeof(list) / sizeof(int);
	int i;
	quickSort(list, 0, length - 1);
	printf("规律分区\n");
	
	for (i = 0; i < length; i++) {
		printf("%d ", list[i]);
	}
}

实现三:随机分区

  1. 思想

​ 由于在极端情况下,选择最左端的位置元素为基准元素,可能会导致快排退化为交换排序,时间复杂度变为 O(n2) 。快速排序算法的性能取决于划分的对称性。通过修改 partition 策略,采用随机选择策略,在 leftright 之间随机选出一个元素作为划分基准,减少极端情况的出现。

  1. 代码
#include <stdio.h>
/*
	稳定性:不稳定

	递归定义:
		  { 1				n=1
	T(n)={
		  { T(n-1) + O(n)	n>1

	平均时间复杂度:O(nlogn)

	最坏时间复杂度:O(n2)
*/

// 交换
void swap(int list[], int left, int right) {
	int temp = list[right];
	list[right] = list[left];
	list[left] = temp;
}

// 分区(算法书中写法)
int partitionAlgorithm(int list[], int left, int right) {
	int pivot = list[left];
	int p = left;

	while (left < right) {
		
		while (left < right && list[right] >= pivot)
			right--;
		while (left < right && list[left] <= pivot)
			left++;

		swap(list, left, right);
	}
	swap(list, p, left);
	return right;
}


// 随机分区
int randomPartition(int list[], int left, int right) {
	int r = rand() % (right - left) + left;
	swap(list, r, left);
	return partitionAlgorithm(list, left, right);
}

// 随机分区的快排
void quickSortR(int list[], int left, int right) {

	if (left < right) {
		int pivot = randomPartition(list, left, right);
		// 左边
		quickSortR(list, left, pivot - 1);
		// 右边
		quickSortR(list, pivot + 1, right);
	}

}

void main() {
	int i;
	int listR[] = {2, 1, 7, 3, 5, 9};
    int length = sizeof(listR) / sizeof(int);
	quickSortR(listR, 0, length - 1);
	printf("\n随机分区\n");

	for (i = 0; i < length; i++) {
		printf("%d ", listR[i]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值