快速排序算法

  1. 冒泡排序:把元素看成一系列的气泡,小的在下,大的再上,再上升期间要相邻的气泡进行比对,大的数往上冒泡。最好的情况下(整个序列是已经排好序的),但仍要进行1/2 n2(等差数列的和)次比较,所以最好情况下的时间复杂度是O(n2),最坏情况下是整个数列完全为逆序,比较和交换都要进行1/2 n2次,总次数是n2次,时间复杂度是O(n2),平均复杂的也是O(n2)。
  2. 插入排序,对一个序列(一开始里面包含的数只有1个)已经排好的序列插入一个数(假设在数组中从小到大排),序列外的元素首先与最大值比较,比最大值大的话存储位置不变,然后序列元素量增加,小的话与最大值交换位置,在与次最大值比较,然后重复,直到找到插入的正确位置。在最坏情况下,即是整个序列正好是逆序排列,需要比较1/2 n2次,交换也是1/2 n2,所以时间复杂度为O(n2)。最好情况下,即是整个序列正好是顺序排列,需要比较n-1次,交换0次时间复杂度为O(n)。根据时间复杂度计算规则(次方留最大,舍常数),他的平均的时间复杂度为:O(n2),当序列中的数据量较小时,选择插入排序会快很多。
  3. 选择排序:在无序的序列中,从某一端的一个元素开始,依次与后面的元素比较大小,满足条件的进行交换,接着从第二个元素开始再与后面的进行逐一比对,接着重复到最后的n-1个元素。最好情况下是顺序排列,无需交换,但比较仍然需要进行1/2 n2次,最坏情况下则额外要交换1/2 n2次。所以平均时间复杂度为O(n2)。
  4. 快速排序算法:将序列排成三段,分为a[left~i] a[i] 和a[i+1~right],使左端的数都满足小于a[i],右端的数大于a[i]。然后再次对左端序列采取上述办法,直到左端的子序列的元素量为1。然后再对右端采取上述办法,也直到右端的子序列元素量为1。
  5. 由于篇幅有限,我们仅对快速排序进行说明。递归方法如下
#include<stdio.h>
#include<stack>
#include<queue>
typedef int Item;
#define key(A) (A)
#define less(A,B) (A<B) //A<B
#define eq(A,B) (!less(A,B) && !less(B,A))
#define swap(A,B) {Item t=A;A=B;B=t;}
#define compswap(A,B) if(less(B,A))swap(A,B)
#define push2(A,B) Push(B,s);Push(A,s);
int partition(Item a[],int l,int r)
{
	int  i = l-1,j=r;
	Item v = a[r];
	int t;
	
	for(;;){
		while(less(a[++i],v));//找大于v的数 
		while(less(v,a[--j]))if(j == l)break;//找小于v的数,要是减到坐标小于传进来的数组下标最小值就跳出 
		if(i>=j)break;//如果i的坐标是之前已经交换过的值的坐标,就跳过 
		swap(a[i],a[j]);//交换值 
		printf("交换的值为:%d %d \n",a[i],a[j]);
	}
	swap(a[i],a[r]);//再将下次用来快速排序的对照值替换至a[i] 
	printf("\n");
	printf("对照值的坐标是:%d\n",i);
	for(int i = 0;i<9;i++)printf(" %d ",a[i]);
	printf("\n");

	return i;//返回新对照值的坐标 
}

void sort(Item a[],int l,int r)
{
	if(r<=l)return;//传进来的数组长度为1时就开始返回 
	int i = partition(a,l,r);//先进行第一次排序,获得划分两个数组的下标先 
	sort(a,l,i-1);
	sort(a,i+1,r);
}
int main()
{
	int i=0;
	int a[8] = {3,1,2,5,6,7,9,10};
	sort(a,0,7);
	while(a[i]){
		printf("%d",a[i++]);
	}
}



  1. 非递归的快速排序,可以用栈或者队列。栈的后进先出的特性可以模仿递归调用。问题的关键是给处理函数分配需要处理数组的区段,即是数组的下标。代码如下
#include<stdio.h>
#include<stdlib.h>
#define key(A) (A)
#define less(A,B) (A<B) 
#define eq(A,B) (!less(A,B) && !less(B,A))
#define swap(A,B) {int t=A;A=B;B=t;}
#define compswap(A,B) if(less(B,A))swap(A,B)
typedef int ListItem;
typedef struct snode *Snode;
typedef struct snode{
	ListItem element;
	Snode next;//栈顶 
}Simul;
typedef struct stack *Stack;
typedef struct stack{
	Snode top;//栈顶 
	Snode curr;//表中 
}Simul1;

Stack ListInit()
{
	Stack L = (Stack)malloc(sizeof(* L));
	L->top = NULL;
	L->curr = NULL;
	return L;
}
int IsEmpty(Stack L)
{
	return L->top == NULL;
}
void ListInsert(Stack L,ListItem x)//只能在栈顶插入 
 {
 	Snode K = (Snode)malloc(sizeof(* L));
 	K->element = x;
 	K->next = L->top; //注意这里的top不是栈中元素 
	L->top = K;
 }
 int ListDellete(Stack L)//只能在栈顶删除,所以只需要传递L即可
 {
 	if(IsEmpty(L)) return 0;
 	L->top = L->top->next; 
  } 
  int partition(int a[],int l,int r)
{
	int  i = l-1,j=r;
	int v = a[r];
	int t;
	
	for(;;){
		while(less(a[++i],v));//找大于v的数 
		while(less(v,a[--j]))if(j == l)break;//找小于v的数,要是减到坐标小于传进来的数组下标最小值就跳出 
		if(i>=j)break;//如果i的坐标是之前已经交换过的值的坐标,就跳过 
		swap(a[i],a[j]);//交换值 
	}
	swap(a[i],a[r]);//再将下次用来快速排序的对照值替换至a[i] 
	printf(" %d ",i);
	return i;//返回新对照值的坐标 
}
void sort(int a[],Stack L)
{
	int i,l,r;
	while(!IsEmpty(L)){
	
		l = L->top->element;r = L->top->next->element;//将栈值取出 
		ListDellete(L);//删除已经取出的栈的值 
		ListDellete(L);
		if(r<=l)continue;
		int i = partition(a,l,r);
		if(r-i>i-l){
	   	ListInsert(L,r);
	    ListInsert(L,i+1); 
		ListInsert(L,i-1);
		ListInsert(L,l);		
		}
		else{
	
		ListInsert(L,i-1);
		ListInsert(L,l);
		ListInsert(L,r);
		ListInsert(L,i+1);
			
		}	 
	}
 } 
 
int main(){
	int i = 0;
	int a[11] = {3,1,2,4,6,7,5,9,8,10};//建议数组容量比实际存储值加一,防止末尾极端情况溢出。 
	Stack L = ListInit();
    ListInsert(L,9);
    ListInsert(L,0);
	sort(a,L);
	while(a[i]){
		printf(" %d ",a[i]);
		i++;
	}
}
  1. 总结,我是被另个一博主的文章点拨到的,思路十分清晰,对我帮助很大。在这里附上链接:该文链接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值