快速排序的递归和非递归实现

        笔者过两天就要去面试,但是连最简单的排序算法都其实还写的不是很清楚,昨天又听了一节左程云老师的公开课吧,原来快速排序的空间复杂度是lon(n)。虽然快速排序大大概实现逻辑心里是清楚的,但是对于边界控制,返回时机真是不甚了了,故而痛定思痛,准备把快速排序的主流的实现都记忆一下。

        以下为笔者写的快速排序递归实现:

#include "stdio.h"
#include "stdlib.h"

void swap(int *a , int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void quicksort(int array[], int start , int end, int len)
{
	if(start<0||end>=len||start>end)
	{
		return 0;
	}
                
                int key = array[end];
                int i = start;
                int j= end-1;
                while(i<=j)//if  len of array equals 2,  recycle needs;
                {
                	while(array[i] < key)
                		i++;
                	while(array[j]>=key&&i<=j)
                		j--;
                	if(i<j)
                	{
                		swap(&array[i], &array[j]);
                	                i++,j--;
                	}
                }
                if(i == end)
                	return;
                swap(&array[i], &array[end]);
                if(i-start>1)
                        quicksort(array, start, i-1, len);
                if(end - i>1)
                        quicksort(array, i+1, end,len);
}

#define len(a)  sizeof(a)/sizeof(int)
int main()
{
    int n;
    scanf("%d",&n);
    int *a=(int*)malloc(n*sizeof(int));
	for(int i =0; i!=n; i++)
        scanf("%d", &a[i]);
	quicksort(a, 0, n-1, n);
	for(int index=0; index!=n; index++)
		printf("%d\n", a[index]);
	return 0;
}

下面是非递归实现,我用链表先实现了一个队列来存储还有哪些快排区间需要排序,每次从队列头取出区间来计算,
然后在队列尾插入划分好的两个需要计算的区间,然后将队列头出队,知道队列为空,则停止计算.其中的partition的
思路和一般的快速排序的思路不太一样,参考了剑指OFFER中的实现,另外一般链表头作为参数一定要用指针的指
针,不然没法修改.
#include "stdio.h"
#include "stdlib.h"

void swap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
typedef  struct  listnode
{
	int start;
	int end;
	struct listnode * next;
}listnode;

typedef listnode**  plisthead;

void push_back(plisthead list, listnode* nodeptr)
{
	if(list==NULL)
	{
		perror("warning:list is null");
		return;
	}
	if(*list == NULL)
		*list = nodeptr;
	else
	{
		listnode * ptail =  *list;
		while(ptail->next != NULL)
			ptail = ptail->next;
		ptail->next = nodeptr;
		nodeptr->next = NULL;
	}
}

listnode* pop_front(plisthead list)
{
	if(list == NULL||(*list)==NULL)
		return NULL;
	listnode *headnode = *list;
	(*list) = headnode->next;
	return headnode;
}

int partition(int array[], int start, int end, int len)
{
	if(start<0||end>=len||start>=end)
		return;
	int key = array[end];
	int small = start -1;
	for(int index=start; index<end; index++)                             //该实现很精巧
	{
		if(array[index]<key)                                       
		{
			small++;
			if(index!=small)
				swap(&array[index], &array[small]);
		}
	}
	++small;                                                                                         //最后不要忘了++small
	swap(&array[small], &array[end]);
	return small;
}

void quicksort(int array[], int len)
{
	listnode * plistnode = (listnode*)malloc(sizeof(listnode));
	plistnode->start = 0;
	plistnode->end   = len-1;
	plistnode->next  = NULL;
	plisthead  phead= &plistnode;                       //首先把链表头数据置为应该进行排序的数组的区间
	while((*phead)!=NULL)
	{
		int partitionpos = partition(array,  (*phead)->start,   (*phead)->end, len);           //进行划分,并得到划分点
		int formerlen = partitionpos - (*phead)->start;
		int latterlen  =  (*phead)->end - partitionpos;
		if(formerlen > 1)
		{
			listnode * plistnode = (listnode*)malloc(sizeof(listnode));
			plistnode->start = (*phead)->start;
			plistnode->end   = partitionpos-1;
			plistnode->next  = NULL;
			push_back(phead, plistnode);
		}
		if(latterlen > 1)
		{
			listnode * plistnode = (listnode*)malloc(sizeof(listnode));
			plistnode->start = partitionpos+1;
			plistnode->end   = (*phead)->end;
			plistnode->next  = NULL;
			push_back(phead, plistnode);
		}
		listnode* pnode = pop_front(phead);
		if(pnode != NULL)
			free(pnode);
	}
	return;
}

int main()
{
	int A[] = {4,3,3,5,2};
	quicksort(A,  5);
	for(int index=0;  index!=5;  index++)
	printf("%d\n", A[index]);
	return 0;
}


非递归实现很容易看出我的实现的额外空间复杂读为O(N/2),其实就相当与二叉树的叶子节点数,

如果用栈结构的话应该能降低到O(logN),当然是在划分比较平均的情况下,一般情况可以通过pivot来选择关键字,增加排序效率.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值