荷蘭國旗

首先是將數組整理成負數在前,正數在後

思想:一次快排,標杆選爲第一個數,確定其最終位置即可

void negtive_front(int a[],int n)
{
	int temp=a[0];
	int i=0,j=n-1;
	while(i<j)
	{
		while(a[j]>=0&&i<j)
		{
			j--;
		}
		if(i<j)
		{
			a[i]=a[j];
			while(a[i]<0&&i<j)
			{
				i++;
			}
			if(i<j)
				a[j]=a[i];
		}
		if(i==j)
			a[i]=temp;
	}
}

將數組整理成負數在前,0在中間,正數在後

思想:荷蘭國旗問題,使用三個指針,一個指針i保證前面全是負數,一個指針p保證前面全是負數和零,一個指針j保證後面全是負數,在p遇到負數時,與i所指swap一下,i++,p++;遇到0,p++;遇到正數,與j所指swap一下,j–,p不動繼續判斷當前位置

void helan_flag(int a[],int n)//使所有的負數在前0在中間正數在後面,各部分內部可以無序
{
	int i=0,j=n-1,p=0;
	while(p<=j)//p<j時 -1 0 3 -1 0不正確,因爲b所指爲0,p同指,應該與r交換。p走到b的左邊才能保證後面的都是正數,不用再看了
	{
		if(a[p]==0)
			p++;
		else if(a[p]<0)
		{
			swap(a[i],a[p]);
			p++;
			i++;
		}
		else if(a[p]>0)
		{
			swap(a[p],a[j]);
		//	p++;//這個不能++
			j--;
		}
	}
}

分成四部分呢,同理,設4個指針

void four_part(int a[],int n)
{
	//eg分爲{0},{一位數},{兩位數},{三位數}
	int i=0,p=0,q=0,j=n-1;
	while(q<=j)
	{
		if(a[q]==0)
		{
			swap(a[i],a[q]);
			i++;
			p++;
			q++;
		}
		else if(a[q]<10)
		{
			swap(a[p],a[q]);
			p++;
			q++;
		}
		else if(a[q]<100)
		{
			q++;
		}
		else 
		{
			swap(a[j],a[q]);
			j--;
		}
	}

}

快排的思想求衆數:將數組整理成三部分,前部分<標杆,中間等於標杆,後部分>標杆,然後判斷哪部分的數超過半數,對其進行遞歸判斷。

int find_half(int a[],int start,int end,int n)
{
	int little=start,middle=start,big=end;//小的放前面,大的放後面
	int temp=a[start];
	while(middle<=big)
	{
		if(a[middle]<temp)
		{
			swap(a[little],a[middle]);
			little++;
			middle++;
		}
		else if(a[middle]==temp)
		{
			middle++;
		}
		else
		{
			swap(a[middle],a[big]);
			big--;
		}
	}
	//判斷哪部分的數過半
	if((big-little+1)>n/2)
		return a[big];//中間的數據
	else if((little-start)>n/2)
		return find_half(a,start,little-1,n);
	else if((end-big)>n/2)
		return find_half(a,big+1,end,n);
	else
		return -1;//沒有這種數據時
}
点赞