快速排序--双边扫描与单边扫描的实现

快速排序 时间复杂读O(N*logN),最差O(N^2),平均O(N*logN)

主要思想是选取一个标志位,大于标志位的放到右边,小于标志位的放到左边,在以标志位为分割,分而制之,左递归,右递归,直到完成。

快速排序的思想(双边扫描)

快速排序就像一个数据快,前后各有一个下标(指针)i/j,随机选取(此处取下标为0的)一个元素作为标志位,存储在临时变量中(tmp),j从后向前移动(j--)直到碰到比tmp还要小的数时与i交换,此时i开始像后走,直到遇到第一个比tmp大的数,与j交换。

递归直至完成。

快速排序思想(单边扫描)

从左到右扫一遍,类似于冒泡排序,只是不停的把小于标志位的值放到左边,大于的放到右边,找到分割位置将标志位放入。

单边扫描怎么把小于标志位(下标end)的放左边,大于标志位的放右边,双边扫描是通过挖坑埋数的方式来实现的,单边扫描可以通过一个small 标志位记录连续最小的哪一个数,index一直向前走找到第一个不连续的小于标志位的值,与small++(第一个大于标志位的值)进行交换,直到循环结束,将small++的值放到标志位end的下标位置。

注:如有错误,望批评指正,算法主要是思想,其次就是按照思想去实现了。

//双边
int partition2(long *str,int start,int end,int length){
	if(str == NULL || length <=1 || start >end)
		return 0;
	int i=start;
	//标志位
        long tmp = str[start];
	int j=end;
	while(i!=j){
		while(i<j && str[j]>tmp)
			j--;
		if(i<j)
			swap(&str[j],&str[i++]);	

		while(i<j && str[i]<tmp)
			i++;
		if(i<j)
			swap(&str[i],&str[j--]);

	}
	swap(&str[i],&tmp);
	return i;
}
//单边扫描
 int  partition(long *str,int start,int end,int length){
	if(str ==NULL || length<=0 || start<0 || end >length)
		return;
	int i=start;
	int small = i-1;
	for(i;i<end;i++){
               //通过对比调整small的位置,直到small的位置到达连续小于标志位的最右端数据
                if(str[i]<str[end]){
			++small;
			if(small != i)
				swap(&str[i],&str[small]);
		}

	}
	++small;
	swap(&str[small],&str[end]);

	return small;
}
//递归调用,实现快速排序
 void quickSort(long *str,int start,int end,int length){
	if(str == NULL || length<1 || start >end)
		return;

	//int mid = quick(str,start,end,length);
	int mid = partition2(str,start,end,length);
	int i=0;
	for(i;i<length;i++)
		printf("%ld\t",str[i]);
	printf("\n");
		quickSort(str,start,mid-1,length);

		quickSort(str,mid+1,end,length);
}

完整代码

运行环境:ubuntu 14.04 kylin、gcc

#include <stdio.h>
#include <malloc.h>
void swap(long *A,long *B){
    long tmp;
    tmp = *A;
    *A = *B;
    *B = tmp;
}
int partition2(long *str,int start,int end,int length){
    if(str == NULL || length <=1 || start >end)
        return 0;
    int i=start;
    long tmp = str[start];
    int j=end;
    while(i!=j){
        while(i<j && str[j]>tmp)
            j--;
        if(i<j)
            swap(&str[j],&str[i++]);    
        
        while(i<j && str[i]<tmp)
            i++;
        if(i<j)
            swap(&str[i],&str[j--]);
        
    }
    swap(&str[i],&tmp);
    return i;
}
int  partition(long *str,int start,int end,int length){
    if(str ==NULL || length<=0 || start<0 || end >length)
        return;
    int i=start;
    int small = i-1;
    for(i;i<end;i++){
        if(str[i]<str[end]){
            ++small;
            if(small != i)
                swap(&str[i],&str[small]);
        }
        
    }
    ++small;
    swap(&str[small],&str[end]);
    
    return small;
}
void quickSort(long *str,int start,int end,int length){
    if(str == NULL || length<1 || start >end)
        return;
    
    //int mid = quick(str,start,end,length);    
    int mid = partition2(str,start,end,length);
    int i=0;
    for(i;i<length;i++)
        printf("%ld\t",str[i]);
    printf("\n");
        quickSort(str,start,mid-1,length);
    
        quickSort(str,mid+1,end,length);
}
int genrand(int num,long * array ){
    if (num>10000)
        return 0 ;
    srand((unsigned int)time(0));
    int i=0;
    for(i=0;i<num;i++)
        array[i] = rand();
    return 1;
    
}
void main(){
    int num = 10;
    long *array=(long *)malloc(sizeof(long)*num) ;
     genrand(num,array);
    
    int i=0;
    /*for(i=0;i<num;i++)
        printf("%ld\n",array[i]);
    */
    quickSort(array,0,9,10);
    printf("\n\n");    
    for(i=0;i<num;i++)
        printf("%ld\n",array[i]);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 18:19:10

快速排序--双边扫描与单边扫描的实现的相关文章

算法整理(二)---快速排序的两种实现方式:双边扫描和单边扫描

首先简单谈下快速排序的特点,时间复杂度O(nLog n),最差时间复杂度O(n^2),平均时间O(nLog n).因为用到了函数栈,空间复杂度为O(lg n),最差为O(n).是一种不稳定的排序方法.基本思想是分治法,这位大大的http://blog.csdn.net/morewindows/article/details/6684558 讲的非常清楚了,分治法+挖坑法,我就不多说了.就是以某个数为参照,使得左边的都小于他,右边的数都大于他.然后对他的左右两个区间采取同样的方法进行递归. 就其整

算法整理(二)---高速排序的两种实现方式:双边扫描和单边扫描

首先简单谈下高速排序的特点,时间复杂度O(nLog n),最差时间复杂度O(n^2),平均时间O(nLog n).由于用到了函数栈,空间复杂度为O(lg n),最差为O(n).是一种不稳定的排序方法.基本思想是分治法,这位大大的http://blog.csdn.net/morewindows/article/details/6684558 讲的很清楚了,分治法+挖坑法,我就不多说了.就是以某个数为參照,使得左边的都小于他,右边的数都大于他.然后对他的左右两个区间採取相同的方法进行递归. 就其总体

高速排序--双边扫描与单边扫描的实现

高速排序 时间复杂读O(N*logN),最差O(N^2),平均O(N*logN) 主要思想是选取一个标志位,大于标志位的放到右边.小于标志位的放到左边.在以标志位为切割,分而制之,左递归,右递归.直到完毕. 高速排序的思想(双边扫描) 高速排序就像一个数据快,前后各有一个下标(指针)i/j,随机选取(此处取下标为0的)一个元素作为标志位.存储在暂时变量中(tmp),j从后向前移动(j--)直到碰到比tmp还要小的数时与i交换,此时i開始像后走,直到遇到第一个比tmp大的数,与j交换. 递归直至完

笔试算法题(54):快速排序实现之单向扫描、双向扫描(single-direction scanning, bidirectional scanning of Quick Sort)

议题:快速排序实现之一(单向遍历) 分析: 算法原理:主要由两部分组成,一部分是递归部分QuickSort,它将调用partition进行划分,并取得划分元素P,然后分别对P之前的部分和P 之后的部分递归调用QuickSort:另一部分是partition,选取划分元素P(随机选取数组中的一个元素,交换到数组末尾位置),定义两个标记 值left和right,随着划分的进行,这两个标记值将数组分成三部分,left之左的部分是小于划分元素P的值,left和right之间的部分是大 于等于划分元素P的

蛋疼的郁闷——聚集索引扫描、非聚集索引扫描、表扫描区别

聚集索引扫描,首先我们知道数据它是以索引键为叶节点排列起来的树形数据结构,表中每行的数据都附属在索引键中,对这样的表进行数据查找时,最快的方式当然是“聚集索引查找”.什么情况下才是“聚集索引扫描”呢?是当你要查找的数据的条件字段上没有索引时,此时查询执行器将对整个表中的数据挨个的进行读取确认符合查询条件的数据,但当该表上有字段设有聚集索引时,该扫描过程称之为“聚集索引扫描",相反的情况是当该表上没有一个字段设有”聚集索引“时,该扫描过程称之为”表扫描“.其实他们本质上的过程都是一样的,就是挨个的

蛋疼的郁闷-聚集索引扫描、非聚集索引扫描、表扫描区别

本文适用于对数据库索引有一定深入的攻城师阅读参考. 我们对于聚集索引扫描和表扫描比较容易理解的,但是对于非聚集索引扫描不太容易理解,这一点也往往容易使初学者感到很是困惑,原因是总认为没必要存在非聚集索引扫描,因为如果查询结果不具有高选择性的话,在聚集索引表中可以使用聚集索引扫描,在对表中会使用表扫描的,那么为什么要会存在非聚集索引扫描呢? 之所以有这样的问题,是因为我们没有考虑到一种情况,那就是查询结果如果被建有非聚集索引的字段覆盖或包含了,而此时where条件字段上的非聚集索引对于本次查询结果

主动扫描和被动扫描的区别

主动扫描和被动扫描知识 对于一个station来说,如果希望连接到AP,首先必须发现AP.发现的方式就两种被动扫描(passive scan)和主动扫描(active scan),记住两个关键字:被动-----听!,主动-----搜! 被动----听什么?-----beacon信标 主动----用什么搜?---probe requests[这个帧里可以携带SSID或者用Null SSID] 注意:客户端如果通过主动扫描发现很多AP具有相同SSID,它会根据信号强度和信号质量选择最佳的AP连接,通

mysql优化 之 group by索引松散扫描和紧凑扫描

group by语句利用B+tree索引扫描时分为松散扫描.紧凑扫描两种情况: Loose Index Scan(松散扫描)就是只需要对索引扫描时取出很小一部分键值就能完成整个sql所需数据的扫描,在where条件含有范围谓词或者无条件.sql语句利用索引就能完成查询的才能使用上松散扫描,用上松散索引扫描的有如下几种类型的语句: 表t1有c1,c2,c3,c4四个字段,index为(c1,c2,c3) SELECT c1, c2 FROM t1 GROUP BY c1, c2;    SELEC

TCP端口扫描类型-隐蔽扫描和僵尸扫描

TCP扫描有三种类型:全连接扫描,隐蔽扫描,僵尸扫描.全连接扫描无须赘述. 隐蔽扫描:发送完SYN数据包以及收到SYN/ACK数据包后不再发送SCK数据包,由于没有建立完整的TCP连接,所以在目标主机的应用日志中不会有扫描的记录,只会在ip层有记录,因而较为隐蔽. 僵尸扫描:条件较为苛刻.首先要能够进行地址欺骗,其次僵尸机没有什么网络流量产生,最后僵尸机的ipid必须是递增的(win xp及以前windows机型). 僵尸扫描的过程: 1 向僵尸机发送SYN/ACK数据包,僵尸机会返回一个RST