1. 程式人生 > >快速排序(遞迴法與迭代法)

快速排序(遞迴法與迭代法)

用遞迴法:程式碼簡潔,但執行速度很慢;

用迭代法:程式碼略多,但執行速度很快。

本文快速排序方法:

用兩個指標i和j,分別指向傳進來的低位地址和高位地址。去中間的數為基準值。i從左向右移動,碰到比基準值小的數就繼續+1,直至i所指向的數為不小於基準值為止。j從右向左移動,碰到比基準值大的數就繼續-1,直至j所指向的數為不大於基準值為止。此時如果滿足i小於等於j,就交換i和j所指向數的值,然後i+1,j-1。整個迴圈一直到i大於j才結束。這時分別將低地址和j,i和高地址分別傳入這個函式實現遞迴。其中,遞迴返回的條件為低地址大於等於高地址。

如果用迭代的話,就要用到棧的特性。將高低地址分別壓棧儲存。每次迴圈開始時就從棧頂取出,一對高低地址進行排序,迴圈結束時要將兩對高低地址分別壓棧儲存。直至棧中沒有元素為止。

程式碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define SIZE 50 //棧的大小

int sl[SIZE];
int sr[SIZE];
int sp = 0;
//入棧
int PUSH(int A, int B) 
{
	sl[sp]=A;
	sr[sp]=B;
	sp++;
}
//出棧
int POP(int* pl, int* pr)
{
	sp--;
	*pl = sl[sp];
	*pr = sr[sp];
}
//迭代法快速排序
void quicksort(int* a,int l,int r)
{
	int i,j,p,t;

	PUSH(l,r);

	while(sp){//棧空即跳出迴圈
		POP(&l,&r);
		i = l;
		j = r;
		p=a[(i+j)/2];//設定基準值(隨意設定,不一定是中間的數)
		while(i<=j) {
			while(a[i]<p)
				i++;
			while(a[j]>p)
				j--;
			if(i<=j){//交換數
				t=a[i];
				a[i]=a[j];
				a[j]=t;
				i++;
				j--;
			}
		}
//判斷是否結束(當l=j時,只有一個元素,不需要排序;
//當l>j時,沒有元素。不需要壓棧)
		if(l<j)
			PUSH(l,j);
		if(i<r)
			PUSH(i,r);
	}
}
//對應的遞迴法快速排序
void sort(int *a, int low, int high)
{
	if(low>=high)
		return;
	int t;
	int p = a[(low+high)/2];
	int i = low;
	int j = high;
	while(i<=j){
		while(a[i]<p)
			i++;
		while(a[j]>p)
			j--;
		if(i<=j){
			t = a[i];
			a[i] = a[j];
			a[j] = t;
			i++;
			j--;
		}
	}
	sort(a,low,j);
	sort(a,i,high);
}

int main()
{
	int a[9] = {34, -13, -12, 33, 0, 12, 9, 4, 18};
	quicksort(a,0, 8);//兩種排序只用一種即可
//	sort(a,0,8);
	int i;
	for(i=0; i<9; i++)
		printf("%d\t", a[i]);
	printf("\n");

	return 0;
}

結果: