(C语言)快排的两种实现

第一种是老师在课上讲的,B站https://www.bilibili.com/video/BV1sJ41127t2 这个视频挺好的我觉得。。
大体是先找一个基准数,从右边开始找一个比他小的(j),放到基准数的位置,从左边开始找(i),找到比基准数大的,放到j的位置,当i=j的时候把基准数放到i(j)这个位置上,然后递归就可以。

#include<stdio.h>
int n;
void qsort(int b[],int l,int r)
{
	if(l>=r) return;
	int i=l,j=r,key=b[l];
	while(i<j){
		while(i<j&&b[j]>=key) j--;
		if(i<j) b[i]=b[j];
		while(i<j&&b[i]<=key) i++;
		if(i<j) b[j]=b[i];
		
	}
	b[i]=key;//这时候i=j,把基准数放进这个位置
	qsort(b,l,i-1);//递归
	qsort(b,i+1,r);
}
int main(){
	int i,j,t,a[100],count;
	scanf("%d",&n);
	for(i=0;i<n;i++) scanf("%d",&a[i]);
	qsort(a,0,n-1);
	for(i=0;i<n;i++)
		printf("%4d",a[i]);
	return 0;
}

第二种是啊哈算法上看到的,具体可以找一下书,讲的很明白。
大体是先确定一个基准数,从右边找一个比它小的(j),然后从左边找一个比它大的(i),如果i<j交换位置,i=j,就把i位置的数跟基准数交换。然后递归。

#include<stdio.h>
void qs(int a[],int l,int r)
{	
	if(l>r) return;
	int i=l,j=r,temp=a[l],t;
	while(i!=j)
	{
		while(i<j&&a[j]>=temp) j--;
		while(i<j&&a[i]<=temp) i++;
		if(i<j)
		t=a[i],a[i]=a[j],a[j]=t;		
	}
	a[l]=a[i];
	a[i]=temp;
	qs(a,l,i-1);
	qs(a,i+1,r);
	return;
}
int main()
{
	int a[10],i,j,n;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	scanf("%d",&a[i]);
	qs(a,0,n-1);
	for(i=0;i<n;i++)
	printf("%4d",a[i]);
	return 0; 
 } 

初学勿喷,有建议评论互相学习

<think>嗯,用户想用C语言实现快速排序算法。首先,我得回忆一下快速排序的基本原理。快速排序是分治法的典型应用,通过选择一个基准元素,将数组分成两部分,左边比基准小,右边比基准大,然后递归处理子数组。对吧? 然后,用户提到的是C语言实现,所以需要具体的代码示例。根据引用资料,有单趟排序的不同方法,比如左右指针法、挖坑法、前后指针法。比如引用3提到快慢指针的方法,可能是指前后指针法,其中i作为慢指针,j作为快指针,根据比较交换元素。 用户提供的示例中有三种单趟排序方法,所以可能需要分别展示不同的实现方式。例如,第一种可能是Hoare的原始方法,左右指针向中间移动,交换不符合条件的元素。第二种是挖坑法,将基准元素的位置作为坑,交替从右左找元素填坑。第三种是前后指针法,慢指针i记录小于基准的边界,j遍历数组。 还要注意递归和非递归的实现。引用1提到了非递归用栈模拟递归,但用户的问题可能更关注基本的递归实现,所以可以先展示递归版本。不过用户提供的参考中有非递归的部分,可能需要简要提及。 另外,时间复杂度方面,引用2指出平均是O(n log n),原地排序但不稳定。这些信息应该在解释时提到,帮助用户理解算法性能。 代码部分需要确保语法正确,比如交换元素使用指针,递归终止条件为数组长度小于等于1。比如引用3中的代码示例,可能需要调整变量名和结构,使其符合C语言的语法。 还需要考虑基准元素的选择,通常选第一个、最后一个或中间元素。不同的选择可能影响代码的实现,比如选第一个元素作为基准,或者像引用3中的例子选最右端作为pivot。 可能用户会混淆不同的实现方法,所以需要明确说明每种方法的步骤,比如左右指针法的步骤,挖坑法的步骤,以及前后指针法的区别。 最后,要检查代码的正确性,确保分区函数正确分割数组,递归调用处理左右子数组,避免死循环或越界错误。例如,在Hoare方法中,左右指针移动的条件和交换的时机是否正确。 总结一下,回答需要分步骤讲解快速排序的原理,展示不同单趟排序方法的C语言实现,解释代码的关键部分,并分析时间复杂度和优化点。同时,确保代码符合C语言的语法规范,如使用指针、正确的循环结构等。</think>### C语言实现快速排序的步骤及方法 快速排序的核心是**分治法**,通过基准元素(pivot)将数组划分为两个子数组,递归排序子数组。以下是三种常见的C语言实现方式及其关键代码: --- #### 方法一:左右指针法(Hoare法) **步骤说明**: 1. 选择最左端元素为基准值(pivot) 2. 左右指针从两端向中间扫描,交换不符合条件的元素 3. 最终将基准值放到正确位置 **代码实现**: ```c int Partition_Hoare(int* arr, int left, int right) { int pivot = arr[left]; int i = left, j = right; while (i < j) { while (i < j && arr[j] >= pivot) j--; while (i < j && arr[i] <= pivot) i++; if (i < j) swap(&arr[i], &arr[j]); } swap(&arr[left], &arr[i]); return i; } void QuickSort(int* arr, int start, int end) { if (start >= end) return; int pivot_idx = Partition_Hoare(arr, start, end); QuickSort(arr, start, pivot_idx - 1); QuickSort(arr, pivot_idx + 1, end); } ``` **特点**:原始方法,移动次数少,但需注意指针越界[^4]。 --- #### 方法二:挖坑法 **步骤说明**: 1. 将最左端元素作为基准值并“挖坑” 2. 右指针向左找小于基准的值填坑,左指针向右找大于基准的值填坑 3. 重复直到指针相遇,最后将基准值填入 **代码实现**: ```c int Partition_Hole(int* arr, int left, int right) { int pivot = arr[left]; int i = left, j = right; while (i < j) { while (i < j && arr[j] >= pivot) j--; arr[i] = arr[j]; while (i < j && arr[i] <= pivot) i++; arr[j] = arr[i]; } arr[i] = pivot; return i; } ``` **特点**:逻辑清晰,适合理解分治过程[^3]。 --- #### 方法三:前后指针法 **步骤说明**: 1. 慢指针`i`记录小于基准的边界,快指针`j`遍历数组 2. 若`arr[j] < pivot`,则`i`右移并交换`i`和`j`的值 3. 最后将基准值与`i+1`位置交换 **代码实现**: ```c int Partition_TwoPointers(int* arr, int left, int right) { int pivot = arr[right]; int i = left - 1; for (int j = left; j < right; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[right]); return i + 1; } ``` **特点**:代码简洁,适合链表结构。 --- #### 时间复杂度分析 - **平均情况**:$O(n \log n)$,分治递归深度为$\log n$,每层比较$n$次[^2] - **最坏情况**:$O(n^2)$(如数组已有序) - **空间复杂度**:$O(\log n)$(递归栈) --- #### 优化建议 1. **三数取中法**:避免最坏情况,选择左、中、右三数的中间值作为基准 2. **小数组切换插入排序**:当子数组长度较小时(如≤10),使用插入排序减少递归开销 3. **尾递归优化**:减少递归调用次数[^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值