zoukankan      html  css  js  c++  java
  • 元素序列几个常用排序算法:一

    在改章节中,我们主要绍介元素序列的内容,自我感觉有个不错的建议和大家分享下

        一、交换排序

        1.冒泡排序:

        冒泡排序的想思就是每次对指定区间行进历遍的同时,较比相邻元素,如果相邻元素为逆序则交换相邻元素,如果位正序则不作任何作操,这样如果按从小到大的次序历遍数组标下,那么一次历遍以后,全部序列中的最小数或者最大数就“下沉”到数组底部了,反之,如果从大到小历遍数组小标,那么一次历遍以后,全部序列中的最小数或者最大数就“上浮”到数组顶部了。

        一般情况下,给定序列区间都是0-n-i)。(当然i-n该应也是可以的,种这情况一般不会现出,因为我们历遍数组的时候,经常是从小标从小到大的次序行进的,所以只能把主要的元素下沉,如果我们从大到小历遍数组标下,是可以到达将主要元素上浮的目标的。这个时候,给定序列就是i-n了。)

     元素和序列

        冒泡排序1,数组标下历遍方法从大到小,给定冒泡区间0-n-i

        

    void bubleSort( int *pArray,const int n, const int type)
    {
    	int i = 0;
    	int j = 0;
    	for (i=1; i<n-1; i++)
    	{
    		for(j=0; j<n-i; j++)
    		{
    			if ( type )
    			{
    				if( pArray[j] < pArray[j+1] )
    				mSwap(pArray+j, pArray+j+1);
    			}
    			else
    			{
    				if( pArray[j] > pArray[j+1] )
    				mSwap(pArray+j, pArray+j+1);
    			}
    		}
    	}
    }

        冒泡排序

        2

        ,数组小标历遍方法从大到小,给定冒泡区间(

        n-1

        )

        -i

        。

        

    void bubleSort1( int *pArray, const int n, const int type )
    {
    	int i = 0;
    	int j = 0;
    	for ( i=0; i<n; i++)
    	{
    		for ( j=n-1; j>i; j--)
    		{
    			if ( type )
    			{
    				if( pArray[j] < pArray[j-1] )
    				mSwap(pArray+j, pArray+j-1);
    			}
    			else
    			{
    				if( pArray[j] > pArray[j-1] )
    				mSwap(pArray+j, pArray+j-1);
    			}
    		}
    	}
    }

        2.快速排序

        

        快排的基本思绪是分治,将待排序列分别为各个小的序列,而对每个序列做的作操是选中一个轴(实际上就是一个数组中某个元素),通过某种法方使得在这个序列中轴的边两分别是比轴大的数和比轴小的数,当排序序列分到充足小时,全部序列就有序了。

        

    void QuickSort (int *pArray, const int left, const int right, const int type)
    {
    	if( left < right )
    	{
    		//先分别
    		int pivotpos = parttition1( pArray, left, right, type);
    		//左部递归(递归的时候,及得要把轴从队列中拿出来)
    		QuickSort( pArray, left, pivotpos-1, type);
    		//右部递归(递归的时候,及得要把轴从队列中拿出来)
    		QuickSort( pArray, pivotpos+1, right, type);
    	}
    }

        对于分别:分别的终究目标是要让序列中的轴边两的元素处于一边是比轴大,一边比轴小的态状,而现实这个目标面下绍介两种法方:

        法方1

        //这里分别的思绪是先把轴的值存保起来,

        //然后用一个指针向指轴的置位(即队首部),

        //接着顺次从序列首部向尾部历遍,找查否是有比轴大(或者比轴小)的元素,

        //一旦有,将它和该指针向指的元素交换,然后再把该指针向队尾挪动一个单位

        //这样做的目标是保障轴指针左边都是比轴大(或者比轴小)的元素,

        //历遍完以后,再将轴指针向指的元素和真正的轴交换

    int parttition( int *pArray, const int low, const int high, const int type)
    {
    	int pivotpos = low;      //轴置位
    	int pivot = pArray[low]; //选中排序序列中第一个置位为轴
    	int i = low + 1;
    	for( i=low+1; i<=high; i++)
    	{
    		if( type ) //从小到大
    		{
    			//保障pivotpos指针左边都是比pivot小的值 
    			if( pArray[i] < pivot && ++pivotpos != i )
    			{
    				mSwap( pArray+pivotpos, pArray+i);
    			}
    		}
    		else //从到达小
    		{
    			//保障pivotpos指针左边都是比pivot大的值
    			if( pArray[i] > pivot && ++pivotpos != i )
    			{
    				mSwap( pArray+pivotpos, pArray+i);
    			}
    		}	
    	}
    	//将正真的轴,和轴指针向指的元素做交换
    	mSwap( pArray+low, pArray+pivotpos);
    	return pivotpos;
    }

        法方2

        //一样首先存保轴的值,这里取队首第一个元素,然后从序列的两头(low和high)向旁边历遍,

        //首先high向队首挪动,一旦找到比轴小的(或大的)元素,将其放到low的置位,

        //然后low向队尾挪动,一旦找到比轴大的(或者小的)元素,将其放到high的置位,

        //这样直到low和high相遇,并且在相遇的时候,low和high就把这个序列成分一边是比轴

        //大的元素,一边是比轴小的元素,最后将轴放到low(或high)的置位。

    int parttition1( int *pArray, const int low, const int high, const int type)
    {
    	int tlow = low;
    	int thigh = high;
    	int pivot = pArray[tlow];
    	while( tlow < thigh )
    	{
    		if( type ) //从小到大排序
    		{
    			//high指针向队尾挪动
    			while(tlow < thigh && pArray[thigh] > pivot )
    			{
    				thigh--;
    			}
    			//找到比pivot小的值,放到low处
    			pArray[tlow] = pArray[thigh];
    			//low指针向队首挪动
    			while( tlow < thigh && pArray[tlow] < pivot )
    			{
    				tlow++;
    			}
    			//找到比pivot大的,放到high处
    			pArray[thigh] = pArray[tlow];
    		}
    		else //从大到小排序
    		{
    			//high指针向队尾挪动
    			while(tlow < thigh && pArray[thigh] < pivot )
    			{
    				thigh--;
    			}
    			//找到比pivot大的值,放到low处
    			pArray[tlow] = pArray[thigh];
    			//low指针向队首挪动
    			while( tlow < thigh && pArray[tlow] > pivot )
    			{
    				tlow++;
    			}
    			//找到比pivot小的,放到high处
    			pArray[thigh] = pArray[tlow];
    		}
    	}
    	//当low和high指针相遇,把轴插入
    	pArray[tlow] = pivot;
    	return tlow;
    }

        我个人较比爱好第一种法方,当然第二种法方实质上也是交换元素的置位,只是一开始留出一个位空,然后每次都把特定元素移到该位空上来,直到最后用轴填充该位空。

        

        

        二、选择排序

        1.直接选择排序:

        选择排序的思绪跟冒泡排序很相似,都是每次对一个序列行进历遍,在历遍完以后短缩该序列的长度(通常是将原序列减去1个元素),然后作为一个新的序列输入行进下一次历遍,直到这个序列中只剩下一个元素为止。选择排序跟冒泡排序的不同之处在于,冒泡排序在历遍中程过是较比两个相邻元素,作操(交换)的时候也是对两个相邻元素行进的;而选择排序历遍的时候,所做的作操是选出当前序列中的最大值,或者最小值,然后把这个最值放在序列的最前端,或者是最后端,下次历遍的时候将把这个选中的值从原队列中剔除,直到队列中只剩下一个元素为止。

        历遍序列0-n-i),每次把选中的最值,放到队列尾部:

    void selectSort( int *pArray, const int n, const int type)
    {
    	int i = 0;
    	int j = 0;
    	int mIndex = 0;
    	int m = 0;
    	if ( !type ) //如果是求最小值
    	{
    		m = AMAX; 
    	}
    	for (i=0; i<n-1; i++)
    	{
    		for (j=0; j<n-i; j++)//历遍序列0-(n-i)
    		{
    			if ( type )  //求最大值
    			{
    				if ( m < pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;//找到最大值的标下
    				}
    			}
    			else //求最小值
    			{
    				if ( m > pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;
    				}
    			}
    		}
    		mSwap(pArray+n-1-i, pArray+mIndex);  //把最大值放到序列尾部
    		//重置最值(m)
    		if ( type ) //求最大值
    		{
    			m = 0;
    		}
    		else  //求最小值
    		{
    			m = AMAX;
    		}
    	}
    }

        历遍序列i-n-1),每次把选中的最值,放到队列首部:

    void selectSort1( int *pArray, const int n, const type )
    {
    	int i = 0;
    	int j = 0;
    	int mIndex = 0;
    	int m = 0;
    	if ( !type ) //如果是求最小值
    	{
    		m = AMAX; 
    	}
    	for (i=0; i<n-1; i++)
    	{
    		for (j=i; j<n; j++)//历遍序列i-(n-1)
    		{
    			if ( type )  //求最大值
    			{
    				if ( m < pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;//找到最大值的标下
    				}
    			}
    			else //求最小值
    			{
    				if ( m > pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;
    				}
    			}
    		}
    		mSwap(pArray+i, pArray+mIndex);  //把最大值放到序列首部
    		//重置最值(m)
    		if ( type ) //求最大值
    		{
    			m = 0;
    		}
    		else  //求最小值
    		{
    			m = AMAX;
    		}
    	}
    }

        不得不说的是,写到这里

        现出了一个挺有意思的小插曲:

        

    void mSwap( int *i, int *j)
    {
    	*i = *i + *j;
    	*j = *i - *j;
    	*i = *i - *j;
    }

        面上是一个交换两个变量的数函,在这个排序程序中咋一看乎似没什么问题,只是没有用规常的法方(用第三个临时变量现实),而是通过传入的这两个变量做加法决解的。但问题往往就出在种这地方。

        面下是现发bug后更进的码代:

    void mSwap( int *i, int *j)
    {
    	if(i != j)     
    	{
    		*i = *i + *j;
    		*j = *i - *j;
    		*i = *i - *j;
    	}
    }

        大家在现该应看出来了。在排序的时候,我们不确定要需交换置位的两个元素在数组中的置位,也就是说两个元素在数组中的置位处同一个置位(即这两个元素是同一个元素)的情况也是可能产生的。而一旦产生这样的情况,面上第一个数函就会出问题了,因为传入的地址,是同一个地址,*i*j的值不管在什么情况下都是同相的。看看码代:

    *I += *j;   //在现改地址空间中的值是本来的两倍
    *j = *I - *j; //由于两次从地址中掏出的值是同相的,所以计算结果为0。 
    *I = *I - *j; //很显然,在现的结果就是0-0了,本来空间中的数功成的被置0,现出bug了。所以用第一个swap数函的时候,排序后的结果有必定概率地现出一些元素的值被置0的情况。

        元素和序列

        如果是规常的法方呢?再看看码代:

    Temp = *I ;  //将该数倒入空杯子
    *I = *j;     //盖覆i的值,实际上是自己值赋给自己
    *j = Temp;   //再从临时变量中取值,由于临时变量只是自己的一个copy,所以也不现出任何问题,也就是说面上的swap数函用规常法方现实,一点问题也不会现出。也许,常用的法方之所以常用,总该是有必定的道理吧。

        这里涉及

        swap

        ,除了面上两种法方之外,用位作操符也可以决解,只是也会现出被置

        0

        的情况:

        

    void mSwap( int *i, int *j)
    {
    	if( i != j)
    	{
    		*i ^= *j;
    		*j ^= *i;
    		*i ^= *j;
    	}
    }

        三、插入排序

        1.直接插入排序:

        打过扑克牌的人,都会这个排序法方。插入排序有一个前提:已排序列是排好序的或者是空的。插入排序的基

        本思绪是,从待排序列中找出一个待排元素i,这时已排序列中会增加一个空置位,用来挪动元素。然后与已排序列中的各个元素行进较比,如果不符合较比条件,将已排序列中的那个元素挪动一个置位,如果符合较比条件就将i插入空置位中,直到待排序列中的所有元素都插入已排序列中。

        元素和序列

    void insertSort( int *pArray, const int n, const int type)
    {
    	int temp;
    	int i = 0;
    	int j = 0;
    	for( i=1; i<n; i++)
    	{
    		//这里temp就是从待排序列中掏出的一个元素
    		//而初始化时待排队列是数组元素1-(n-1)置位上n-1个元素
    		//已排队列是数组中头部第一个元素
    		temp = pArray[i];
    		j = i;
    	
    		if( type )//从小到大排列
    		{
    			//如果满足左大右小,所有数组中的元素从左向右挪动
    			//如果temp最小,它将被插到数组头部
    			while( j>0 && pArray[j-1] > temp )
    			{
    				pArray[j] = pArray[j-1]; 
    				j--;
    			}
    		}
    		else //从大到小排列
    		{
    			//如果temp最小,它将被插到数组头部
    			while( j>0 && pArray[j-1] < temp )
    			{
    				pArray[j] = pArray[j-1]; 
    				j--;
    			}
    		}
    		//如果挪动到数组头部,或者找到合适的置位,将元素插入
    		pArray[j] = temp;
    	}
    }

        2.二分插入排序

        每日一道理
    这浓浓的母爱使我深深地认识到:即使你是一只矫健的雄鹰,也永远飞不出母爱的长空;即使你是一条扬帆行驶的快船,也永远驶不出母爱的长河!在人生的路上不管我们已走过多远,还要走多远,我们都要经过母亲精心营造的那座桥!

        在直接插入排序中,将一个元素插入到已排好序的队列中是直接从一头到另一头的线性找查,效率不高。而由于已排序列是已经排好序的,所以在找查插入置位的时候,可以利用二分找查来提高效率。

    void binaryInsertSort( int *pArray, const int n, const int type)
    {
    	int temp;
    	int i = 0;
    	int j = 0;
    	int left = 0;
    	int right = 0;
    	int middle = 0;
    	for( i=1; i<n; i++)
    	{
    		temp = pArray[i];
    		//二分找查,寻找插入置位
    		left = 0;
    		right = i - 1;
    		while( left <= right )
    		{
    			middle = ( left + right ) / 2;
    			if( type ) //从大到小
    			{
    				if( temp < pArray[middle] )
    				{
    					left = middle + 1;
    				}
    				else
    				{
    					right = middle - 1;
    				}
    			}
    			else //从小到大
    			{
    				if( temp > pArray[middle] )
    				{
    					left = middle + 1;
    				}
    				else
    				{
    					right = middle - 1;
    				}
    			}
    			
    		}
    		//成块的移出插入置位
    		for( j=i-1; j>=left; j--)
    		{
    			pArray[j+1] = pArray[j];
    		}
    		//插入元素
    		pArray[left] = temp; 
    	}
    }

        3.Shell排序

        不管是在直接插入排序中,还是在二分插入排序中,最耗时间的是找查插入置位的过程。而对于基本有序的序列来说,寻找插入置位的过程可以省去很多时间。也就是说在排序序列具有必定有序性的情况下,插入排序的效率可以很大的提高。Shell排序的思绪就是逐渐提高排序序列的有序性,直到全部序列式完全有序的。

        具体的做法是选取一个gap值,用这个值每次选取待排队列中的某些元素,组成一个子序列,然后对子序列行进直接插入排序,接着缩小gap的值,再选取子序列再排序,直到最后gap==1(此时待排序列的有序程度已经很高了),再行进一次直接插入排序。

        Shell排序中gap的取值法方有很多种,孰优孰劣,众说纷纭。最初提出来的时候gap=n/2, gap/=2;后来提出取:gap = gap / 3 + 1;还有些人提出取奇数,也有人提出取的gap值互为素数较好。

        Shell排序:

    void shellSort( int *pArray, const int n, const int type)
    {
    	int gap = n/2;  //首次选取gap值为n/2
    	int i = 0;
    	int j = 0;
    	int temp = 0;
    	while( gap )
    	{
    		for( i=gap; i<n; i+=gap)
    		{
    			temp = pArray[i];
    			j = i;
    			if( type ) //从大到小
    			{
    				while( j>0 && temp > pArray[j-gap])
    				{
    					pArray[j] = pArray[j-gap];
    					j = j - gap;
    				}
    			}
    			else  //从小到大
    			{
    				while( j>0 && temp < pArray[j-gap])
    				{
    					pArray[j] = pArray[j-gap];
    					j = j - gap;
    				}
    			}	
    			pArray[j] = temp;
    		}
    		gap /= 2;  //每次gap值折半
    	}
    }

        再给出一个面上排序算法的测试程序,暂时就到这儿吧。

        测试程序:

        

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define AMAX 10000   //数组元素中的最大值
    #define LEN 100     //数组长度
    
    /*
    * 打印出数组中的所有元素
    */
    void printArray( int *pArray, const int n)
    {
    	int i = 0;
    	for (i=0; i<n; i++)
    	{
    		printf("%d ", pArray[i]);
    	}
    	printf("\n\n");
    }
    
    /*
    * 寻找数组中的最大值
    */
    void findMaxAndMin( int *pArray, const int n)
    {
     	int max = 0;
    	int min = AMAX;
    	int i = 0;
    	for (i=0; i<n; i++)
    	{
    		if ( max < pArray[i])
    		{
    			max = pArray[i];
    		}
    		if ( min > pArray[i])
    		{
    			min = pArray[i];
    		}
    	}
    	printf("Max: %d, Min: %d\n", max, min);
    }
    
    /*
    * 交换两个元素
    */
    void mSwap( int *i, int *j)
    {
    	if(i != j)     
    		//一个很有意思的bug,这里,如果i和j这两个地址
    		//是同一个地址的话,在swap以后,地址中的数变为0,
    		//表面上,我们要交换这个数组中的两个元素,但由于某种原因这两个元素
    		//在数组中处于同一置位(也就是同一个元素),交换以后的结果(地址中的数变为0)并不是我们想要的(地址中的数不变)。
    		//如果这里的swap用第三个变量来现实的话,是不会现出种这情况的。
    	{
    		*i = *i + *j;
    		*j = *i - *j;
    		*i = *i - *j;
    	}
    }
    
    /*
    * 冒泡排序
    */
    void bubleSort1( int *pArray, const int n, const int type )
    {
    	int i = 0;
    	int j = 0;
    	for ( i=0; i<n; i++)
    	{
    		for ( j=n-1; j>i; j--)
    		{
    			if ( type )
    			{
    				if( pArray[j] < pArray[j-1] )
    				mSwap(pArray+j, pArray+j-1);
    			}
    			else
    			{
    				if( pArray[j] > pArray[j-1] )
    				mSwap(pArray+j, pArray+j-1);
    			}
    		}
    	}
    }
    
    /*
    * 冒泡排序
    */
    void bubleSort( int *pArray,const int n, const int type)
    {
    	int i = 0;
    	int j = 0;
    	for (i=1; i<n-1; i++)
    	{
    		for(j=0; j<n-i; j++)
    		{
    			if ( type )
    			{
    				if( pArray[j] < pArray[j+1] )
    				mSwap(pArray+j, pArray+j+1);
    			}
    			else
    			{
    				if( pArray[j] > pArray[j+1] )
    				mSwap(pArray+j, pArray+j+1);
    			}
    		}
    	}
    }
    
    /*
    * 选择排序
    */
    void selectSort( int *pArray, const int n, const int type)
    {
    	int i = 0;
    	int j = 0;
    	int mIndex = 0;
    	int m = 0;
    	if ( !type ) //如果是求最小值
    	{
    		m = AMAX; 
    	}
    	for (i=0; i<n-1; i++)
    	{
    		for (j=0; j<n-i; j++)//历遍序列0-(n-i)
    		{
    			if ( type )  //求最大值
    			{
    				if ( m < pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;//找到最大值的标下
    				}
    			}
    			else //求最小值
    			{
    				if ( m > pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;
    				}
    			}
    		}
    		mSwap(pArray+n-1-i, pArray+mIndex);  //把最大值放到序列尾部
    		//重置最值(m)
    		if ( type ) //求最大值
    		{
    			m = 0;
    		}
    		else  //求最小值
    		{
    			m = AMAX;
    		}
    	}
    }
    
    /*
    * 选择排序
    */
    void selectSort1( int *pArray, const int n, const type )
    {
    	int i = 0;
    	int j = 0;
    	int mIndex = 0;
    	int m = 0;
    	if ( !type ) //如果是求最小值
    	{
    		m = AMAX; 
    	}
    	for (i=0; i<n-1; i++)
    	{
    		for (j=i; j<n; j++)//历遍序列i-(n-1)
    		{
    			if ( type )  //求最大值
    			{
    				if ( m < pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;//找到最大值的标下
    				}
    			}
    			else //求最小值
    			{
    				if ( m > pArray[j])
    				{
    					m = pArray[j];
    					mIndex = j;
    				}
    			}
    		}
    		mSwap(pArray+i, pArray+mIndex);  //把最大值放到序列首部
    		//重置最值(m)
    		if ( type ) //求最大值
    		{
    			m = 0;
    		}
    		else  //求最小值
    		{
    			m = AMAX;
    		}
    	}
    }
    
    /*
    * 直接插入排序
    */
    void insertSort( int *pArray, const int n, const int type)
    {
    	int temp;
    	int i = 0;
    	int j = 0;
    	for( i=1; i<n; i++)
    	{
    		//这里temp就是从待排序列中掏出的一个元素
    		//而初始化时待排队列是数组元素1-(n-1)置位上n-1个元素
    		//已排队列是数组中头部第一个元素
    		temp = pArray[i];
    		j = i;
    		
    		if( type )//从小到大排列
    		{
    			//如果满足左大右小,所有数组中的元素从左向右挪动
    			//如果temp最小,它将被插到数组头部
    			while( j>0 && pArray[j-1] > temp )
    			{
    				pArray[j] = pArray[j-1]; 
    				j--;
    			}
    		}
    		else //从大到小排列
    		{
    			//如果temp最小,它将被插到数组头部
    			while( j>0 && pArray[j-1] < temp )
    			{
    				pArray[j] = pArray[j-1]; 
    				j--;
    			}
    		}
    		//如果挪动到数组头部,或者找到合适的置位,将元素插入
    		pArray[j] = temp;
    	}
    }
    
    /*
    * 二分插入排序
    */
    void binaryInsertSort( int *pArray, const int n, const int type)
    {
    	int temp;
    	int i = 0;
    	int j = 0;
    	int left = 0;
    	int right = 0;
    	int middle = 0;
    	for( i=1; i<n; i++)
    	{
    		temp = pArray[i];
    		//二分找查,寻找插入置位
    		left = 0;
    		right = i - 1;
    		while( left <= right )
    		{
    			middle = ( left + right ) / 2;
    			if( type ) //从大到小
    			{
    				if( temp < pArray[middle] )
    				{
    					left = middle + 1;
    				}
    				else
    				{
    					right = middle - 1;
    				}
    			}
    			else //从小到大
    			{
    				if( temp > pArray[middle] )
    				{
    					left = middle + 1;
    				}
    				else
    				{
    					right = middle - 1;
    				}
    			}
    			
    		}
    		//成块的移出插入置位
    		for( j=i-1; j>=left; j--)
    		{
    			pArray[j+1] = pArray[j];
    		}
    		//插入元素
    		pArray[left] = temp; 
    	}
    }
    
    /*
    * Shell 排序
    */
    void shellSort( int *pArray, const int n, const int type)
    {
    	int gap = n/2;  //首次选取gap值为n/2
    	int i = 0;
    	int j = 0;
    	int temp = 0;
    	while( gap )
    	{
    		for( i=gap; i<n; i+=gap)
    		{
    			temp = pArray[i];
    			j = i;
    			if( type ) //从大到小
    			{
    				while( j>0 && temp > pArray[j-gap])
    				{
    					pArray[j] = pArray[j-gap];
    					j = j - gap;
    				}
    			}
    			else  //从小到大
    			{
    				while( j>0 && temp < pArray[j-gap])
    				{
    					pArray[j] = pArray[j-gap];
    					j = j - gap;
    				}
    			}	
    			pArray[j] = temp;
    		}
    		gap /= 2;  //每次gap值折半
    	}
    }
    
    /*
    * 分别,根据选中的轴把排序序列分别为两个部分
    */
    int parttition( int *pArray, const int low, const int high, const int type)
    {
    	//这里分别的思绪是先把轴的值存保起来,
    	//然后用一个指针向指轴的置位(即队首部),
    	//接着顺次从序列首部向尾部历遍,找查否是有比轴大(或者比轴小)的元素,
    	//一旦有,将它和该指针向指的元素交换,然后再把该指针向队尾挪动一个单位
    	//这样做的目标是保障轴指针左边都是比轴大(或者比轴小)的元素,
    	//历遍完以后,再将轴指针向指的元素和真正的轴交换
    	int pivotpos = low;      //轴置位
    	int pivot = pArray[low]; //选中排序序列中第一个置位为轴
    	int i = low + 1;
    	for( i=low+1; i<=high; i++)
    	{
    		if( type ) //从小到大
    		{
    			//保障pivotpos指针左边都是比pivot小的值 
    			if( pArray[i] < pivot && ++pivotpos != i )
    			{
    				mSwap( pArray+pivotpos, pArray+i);
    			}
    		}
    		else //从到达小
    		{
    			//保障pivotpos指针左边都是比pivot大的值
    			if( pArray[i] > pivot && ++pivotpos != i )
    			{
    				mSwap( pArray+pivotpos, pArray+i);
    			}
    		}	
    	}
    	//将正真的轴,和轴指针向指的元素做交换
    	mSwap( pArray+low, pArray+pivotpos);
    	return pivotpos;
    }
    
    /*
    * 分别2,根据选中的轴把排序序列分别为两个部分
    */
    int parttition1( int *pArray, const int low, const int high, const int type)
    {
    	//除了面上的分别法方之外,还有一种法方
    	//首先存保轴的值,这里取队首第一个元素,然后从序列的两头(low和high)向旁边历遍,
    	//首先high向队首挪动,一旦找到比轴小的(或大的)元素,将其放到low的置位,
    	//然后low向队尾挪动,一旦找到比轴大的(或者小的)元素,将其放到high的置位,
    	//这样直到low和high相遇,并且在相遇的时候,low和high就把这个序列成分一边是比轴
    	//大的元素,一边是比轴小的元素,最后将轴放到low(或high)的置位。
    	int tlow = low;
    	int thigh = high;
    	int pivot = pArray[tlow];
    	while( tlow < thigh )
    	{
    		if( type ) //从小到大排序
    		{
    				//high指针向队尾挪动
    				while(tlow < thigh && pArray[thigh] > pivot )
    				{
    					thigh--;
    				}
    				//找到比pivot小的值,放到low处
    				pArray[tlow] = pArray[thigh];
    				//low指针向队首挪动
    				while( tlow < thigh && pArray[tlow] < pivot )
    				{
    					tlow++;
    				}
    				//找到比pivot大的,放到high处
    				pArray[thigh] = pArray[tlow];
    		}
    		else //从大到小排序
    		{
    				//high指针向队尾挪动
    				while(tlow < thigh && pArray[thigh] < pivot )
    				{
    					thigh--;
    				}
    				//找到比pivot大的值,放到low处
    				pArray[tlow] = pArray[thigh];
    				//low指针向队首挪动
    				while( tlow < thigh && pArray[tlow] > pivot )
    				{
    					tlow++;
    				}
    				//找到比pivot小的,放到high处
    				pArray[thigh] = pArray[tlow];
    		}
    	}
    	//当low和high指针相遇,把轴插入
    	pArray[tlow] = pivot;
    	return tlow;
    }
    
    /*
    * 快排
    */
    void QuickSort (int *pArray, const int left, const int right, const int type)
    {
    	if( left < right )
    	{
    		//先分别
    		int pivotpos = parttition1( pArray, left, right, type);
    		//左部递归(递归的时候,及得要把轴从队列中拿出来)
    		QuickSort( pArray, left, pivotpos-1, type);
    		//右部递归(递归的时候,及得要把轴从队列中拿出来)
    		QuickSort( pArray, pivotpos+1, right, type);
    	}
    }
    
    void quickSort( int *pArray, const int n, const int type )
    {
    	QuickSort( pArray, 0, n-1, type);
    }
    
    int main()
    {	
    	int i = 0;
    	int marray[LEN] = {0};
    	srand(time(0));
    	for ( i=0; i<LEN; i++)
    	{
    		marray[i] = rand() % AMAX + 1;
    	}
    	//findMaxAndMin(marray, LEN);
    
    	printf("SORT1:\n");
    	printf("Before Sort:\n");
    	printArray(marray, LEN);
    	quickSort(marray, LEN, 1);
    	printf("After Sort:\n");
    	printArray(marray, LEN);
    
    	printf("SORT2:\n");
    	printf("Before Sort:\n");
    	printArray(marray, LEN);
    	quickSort(marray, LEN, 0);
    	printf("After Sort:\n");
    	printArray(marray, LEN);
    
    /*
    	printf("SORT2:\n");
    	printf("Before Sort:\n");
    	printArray(marray, LEN);
    	bubleSort1( marray, LEN,0);
    	printf("After Sort:\n");
    	printArray(marray, LEN);
    */
    	return 0;
    }

        

    文章结束给大家分享下程序员的一些笑话语录: 小沈阳版程序员~~~ \n程序员其实可痛苦的了......需求一做一改,一个月就过去了;嚎~ \n需求再一改一调,一季度就过去了;嚎~ \n程序员最痛苦的事儿是啥,知道不?就是,程序没做完,需求又改了; \n程序员最最痛苦的事儿是啥,知道不? 就是,系统好不容易做完了,方案全改了; \n程序员最最最痛苦的事儿是啥,知道不? 就是,系统做完了,狗日的客户跑了; \n程序员最最最最最痛苦的事儿是啥,知道不? 就是,狗日的客户又回来了,程序给删没了!

  • 相关阅读:
    NYOJ 625 笨蛋的难题(二)
    NYOJ 102 次方求模
    ZJU Least Common Multiple
    ZJUOJ 1073 Round and Round We Go
    NYOJ 709 异形卵
    HDU 1279 验证角谷猜想
    BNUOJ 1015 信息战(一)——加密程序
    HDU 1202 The calculation of GPA
    "蓝桥杯“基础练习:字母图形
    "蓝桥杯“基础练习:数列特征
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3060064.html
Copyright © 2011-2022 走看看