算法练习(分治法,分区思想)


GetMaxMin.h

#ifndef _GETMAXMIN_H_
#define _GETMAXMIN_H

Demo1
struct MaxMin
{
	int min;
	int max;
};

MaxMin GetMaxMin(int *arr,int beg,int end)
{
	MaxMin maxmin,maxmin1,maxmin2;
	int mid;
	if(beg == end)
	{
		maxmin.min = arr[beg];
		maxmin.max = arr[end];
		return maxmin;//
	}
	else if(end - 1 == beg)
	{
		maxmin.max = arr[beg] > arr[end] ? arr[beg]: arr[end];
		maxmin.min = arr[beg] < arr[end] ? arr[beg]: arr[end];
		
		return maxmin;//
	}

	else
	{
		mid = (beg + end)/2;
		maxmin1 = GetMaxMin(arr,beg,mid);
		maxmin2 = GetMaxMin(arr,mid + 1,end);
		//合并两个区间的最大值和最小值
		maxmin.max = maxmin1.max > maxmin2.max ? maxmin1.max : maxmin2.max;
		maxmin.min = maxmin1.min < maxmin2.min ? maxmin1.min : maxmin2.min;
		return maxmin;//
	}
}

///Demo2
//arr[0...n-1]中大于arr[n]的数字
int GreaterNumCount(int *arr,int n/*,int num*/)
{
	int count = 0;
	for(int i = 0;i<=n ;i++)
		if(arr[i] > arr[n+1])
			count++;
	return count;
}



//f(0) = 0; f(1) = 1 or 0;  f(n) = f(n-1) + arr[0...n-1]中大于arr[n]的数字
int GetReverseNum(int *arr,int n)
{
	if(n == 0)
		return 0;
	else if(n == 1)
		return arr[0] > arr[1] ? 1 : 0;
	else// n >=2
	{
		return GetReverseNum(arr,n-1) + GreaterNumCount(arr,n-1/*,arr[n]*/);
	}
}

Dem3

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


int Partion(int *arr,int n)//0-n
{
	int pivot = 0;
	int p_val = arr[0]; 
	int i = 1,j=n;
	while(1)
	{
		while(arr[i] < p_val) 
		{
			i++;
			if(i > n)
			{
				//can do nothing here
				//swap(arr[pivot],arr[n]);
				return n;
			}
		}
		while(arr[j] > p_val)
			j--;

		if(i<j)
			swap(arr[i],arr[j]);
		else//i>=j
		{
			//0 -6 -6 -5 6 9 4  --> j = -5   
			//swap(arr[j],p_val);//可以不交换
			return j;
		}
	}
}



///Demo4
int Partition(int *arr,int beg,int end)
{
	int pivot = beg;
	int s = arr[beg];
	int i = beg + 1,j = end;//----i = beg + 1
	while(1)
	{
		while(arr[i] < s)
		{
			i++;
			if(i > end)// 5 4 3 2 
			{
				swap(arr[end],arr[pivot]);
				return end;
			}
		}
		while(arr[j] > s)
			j--;

		if(i < j)
			swap(arr[i],arr[j]);
		else//i<=j
		{
			//swap(arr[j],s);//error  应该交换数组对应位置的元素
			swap(arr[j],arr[pivot]);
			return j;
		}
	}
}


void QS(int *arr,int beg,int end)
{/*如递归所有控件路径,函数将导致运行时堆栈溢出*/
	//int s = Partition(arr,beg,end); 

	int s;
	if(beg<end)
	{
		s = Partition(arr,beg,end);
		QS(arr,beg,s-1);// 
		QS(arr,s+1,end);
	}

}


//Demo5


void PartionOddEven(int *arr,int n)//0-n
{
	int pivot = 0;
	int p_val = arr[0]; 
	//int i = 1,j=n;
	int i = 0,j = n;

	while(1)
	{
		while(arr[i]%2 == 1) //奇数
		{
			i++;
			if(i > n)//注意 全是偶数的情况
			{
				//can do nothing here
				//swap(arr[pivot],arr[n]);
				//return n;
				break;
			}
		}
		while(arr[j]%2 ==0)// 
		{
			j--;
			if(j < 0)//注意 全是偶数的情况
				break;//
		}

		if(i<j)
			swap(arr[i],arr[j]);
		else
			break;
		/*
		else//i>=j
		{
			//0 -6 -6 -5 6 9 4  --> j = -5   
			//swap(arr[j],p_val);//可以不交换
			return j;
		}
		*/
	}
}


//Demo6
//RWB

void swap(char &a,char &b)
{
	char tmp;
	tmp = a;
	a = b;
	b = tmp;
}

//RRBWBR
void RangeFlag(char *arr,int n)
{
	int beg = 0,end = n;//beg前面的都已经排好了 end后面的都已经排好了
	int cur = 0;
	char tmp;

	while(cur <= end)//end的右边全是B  停止判断
	{
		if(arr[cur] == 'R')
		{
			swap(arr[beg],arr[cur]);
			
			//beg = cur;
			beg ++;//-------
			cur ++;
		}
		else if(arr[cur] == 'W')
		{
			cur ++;
		}
		else//B
		{
			
			swap(arr[cur],arr[end]);

			end --;

		}
	}
}
/*
设置两个标志位begin和end分别指向这个数组的开始和末尾,然后用一个标志位current从头开始进行遍历:


1)若遍历到的位置为R,则说明它一定属于前部,于是就和begin位置进行交换,然后current向前进,
begin也向前进(表示前边的已经都排好了)。

2)若遍历到的位置为W,则说明它一定属于中部,根据总思路,中部的我们都不动,然后current向前进。

3)若遍历到的位置为B,则说明它一定属于后部,于是就和end位置进行交换,由于交换完毕后current指向的可能是属于前部的,
若此时current前进则会导致该位置不能被交换到前部,所以此时current不前进。而同1),end向后退1。


*/
#endif
  


#include <iostream>
#include <string.h>
#include <algorithm>

#include "GetMaxMin.h"


using namespace std;



int main()
{

	//1.同时求最大值和最小值
	cout << "Max and Min:" << endl; 
	int arr[11] = {-119,8,9,2,5,-7,10,200,3,-7,201};
	MaxMin maxmin;
	maxmin = GetMaxMin(arr,0,10);
	cout << "max: " << maxmin.max << " min:" << maxmin.min << endl;

	//求逆置数的对数
	//int arr2[5] = {2,3,3,2,1};
	int arr2[5] = {2,2,2,2,2};
	cout << "GetReverseNum: " << GetReverseNum(arr2,4) << endl;

	


	//负数放到正数前面
	cout << "负数放到正数前面:" << endl;
	//int arr3[7] = {0,-3,-9,-8,-5,-2,-9};
	int arr3[7] = {0,-3,4,6,7,-2,9};
	int p = Partion(arr3,6);//---------------------
	cout << "partion point:" << p << endl;
	for(int i = 1;i<=6;i++)
		cout << arr3[i] << " ";
	cout << endl;


	//快速排序
	int arr4[7] = {0,-3,-9,2,-5,11,11};
	QS(arr4,0,6);
	cout<< "QuickSort:"<< endl;
	for(int i = 0;i<=6;i++)
		cout << arr4[i] << " ";
	cout << endl;

	copy(arr4,arr4 + 7,ostream_iterator<int,char>(cout," "));//注意第二个参数应该为超尾迭代器
	cout << endl;


	//奇数放到偶数前面
	cout << "奇数放到偶数前面:" << endl;
	//int arr5[6] = {3,8,1,9,4,0};
	//int arr5[6] = {2,8,9,2,6,4};
	//int arr5[6] = {2,8,20,2,6,4};
	int arr5[6] = {1,9,3,5,21,33};

	PartionOddEven(arr5,5);
	copy(arr5,arr5 + 6,ostream_iterator<int,char>(cout," "));
	cout << endl;

	//三色国旗
	cout << "三色国旗:" << endl;
	//char *flags = "RRBWBR";//error 常量不可修改
	char flags[] = {"RRBWRWBBBRWR"};
	//char flags[] = {"BBBBBBBBB"};
	//char flags[] = {"RRRRRRRR"};

	//char flags[] = {"RRWWBB"};
	//char flags[] = {"WBRRWRBW"};

	RangeFlag(flags,strlen(flags) - 1);
	cout << flags << endl;

	return 0;
}


 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值