用堆栈完成进制转换 (使用堆栈的方法)

使用堆栈stack来实现取数组合,有这样一种需求,分别从10个集合中取一个数,组合成10个数是组合,不考虑排序,10几个集合每个集合包含3个数,

这个该如何实现呢?这个组合数有3的10次方,很多人会考虑使用for循环来实现,如下面的方法:


		for(int j=0;j<3;j++){
			int a1=arr[0][j];
			for(int k=0;k<3;k++){
				int a2=arr[1][k];
				System.out.println("-->:"+ a1+" "+a2);
				count++;
			}
		}

如果集合的个数小于3,使用3层for循环就可以了,如果是10个集合,那岂不是要10层for循环,可能你你会说10层也不算多,照样能实现。如果需求是20个集合、30个、100个集合呢?

你不可能写100层for循环代码吧,这是不现实的。

所以我们要使用java的堆栈的思想来实现。这里使用二维数组为代表集合,如int[6][3] arr 代表6个集合,每个集合3个元素。 使用一个索引数组来标识当前二维数组中遍历的索引位置

大概思路就是栈顶不断遍历,直到遍历当前集合所有元素,然后出栈,使下一个新的栈顶遍历完集合,直到栈中所有元素都是集合的最大索引时,则整个过程遍历完成。

为了更好理解,这里举2个集合,每个集合大小为3 ,最大索引为2 为例:

一开始都是从0开始遍历,入栈为 [0] ,元素未满,下一个集合继续入栈,[0]--[0,0] 判断栈顶0小于2,

开始遍历栈顶,[0,0]---0出栈-----[0]----1入栈--->[0,1]---1出栈--[0]--2入栈->[0,2] ,

此时栈顶为2,出栈,集合2遍历完成,不再入栈,[0,2]-- 2出栈--->[0]

开始集合1下一轮的遍历,[0]---0出栈-->[]---1入栈--[1],

元素未满,下一个集合继续入栈,[1]--[1,0] 判断栈顶0小于2,

开始遍历栈顶,[1,0]---0出栈-----[1]----1入栈--->[1,1]---1出栈--[1]--2入栈->[0,2] ,

此时栈顶为2,出栈,集合2遍历完成,不再入栈,[1,2]-- 2出栈--->[1]

开始集合1下一轮的遍历,[1]---1出栈-->[]---2入栈--[2],

元素未满,下一个集合继续入栈,[2]--[2,0] 判断栈顶0小于2,

开始遍历栈顶,[2,0]---0出栈-----[2]----1入栈--->[2,1]---1出栈--[2]--2入栈->[2,2] ,

此时栈顶为2,[2,2]---出栈-->[2],栈顶还是2,[2]继续出栈--->[]

此时栈已经为空了,所有组合已经遍历完成

这里的关键点就是,下轮循环时,栈顶后面的索引数组的值要复位为0

代码如下:

/**
	 * 分别取int[n][m] 二维数组中一个元素,组合成n这个数字,遍历每个子数组的m元素
	 */
	public static void  comby(){
		
		int[][] arr={
		{2,4},
		{9,10},
		{14,16},
		{21,22}
};
		
		int width=arr[0].length;//二维数组的宽度
		
		/**
		 * indexOfArr标记每个集合,即每个二维子数组当前遍历的索引,最大索引为 上面的width
		 */
		int[] indexOfArr =new int[arr.length];//标记二维数组,当前打印的索引,每组标记数组 的索引值      6组
		for(int i=0;i<indexOfArr.length;i++){
			indexOfArr[i]=0;
		}
	
		Stack<Integer> stack=new Stack<>();
		
		stack.push(indexOfArr[0]);
		//stack.push(n[1]);
		List<Stack<Integer>>list=new ArrayList<>();
		
		
		while(stack.size()>0){
			/**
			 * 拼组合
			 */
			if(stack.size()<indexOfArr.length){
				for(int i=stack.size();i<indexOfArr.length;i++){
					stack.add(indexOfArr[i]);
				}
			}
			
			//用来打印每种的堆栈
			Stack<Integer> prstack=new Stack<>();
			
			for(int i=0;i<stack.size();i++){
				prstack.push(stack.get(i));
			}
			//只要栈顶小 于width-1 ,出栈
			list.add(prstack);
			
			//还未遍历完的,继续遍历  
			/*
			 * stack.peek()==width-1 表示当前集合已经遍历完成,出栈,改变前一个集合的索引遍历
			 * 如果栈中的所有元素都是width-1,表示所有集合都已经遍历完了,此时栈会被清空,也就遍历完了
			 * */
			while(stack.size()>0&&stack.peek()==width-1){
				stack.pop();
			}
			if(stack.size()>0&&stack.peek()<width-1){
				indexOfArr[stack.size()-1]++;
				stack.pop();
				stack.push(indexOfArr[stack.size()]);
				//后面的元素变成0开始
				for(int i=stack.size();i<indexOfArr.length;i++){
					indexOfArr[i]=0;
				}

			}
		}
		
		System.out.println("------分界线###########-------------");
		System.out.println("-->:"+list);
		System.out.println("-------分界线###########-------------");
		System.out.println("-------打印组合-------------");
		//打印所有的组合
		for(Stack<Integer> s:list){
			String str="";
			for(int i=0;i<s.size();i++){
				str=str+ arr[i][s.get(i)] +" ";
			}		
			System.out.println();
			
			System.out.println("组合-->:"+ str);
		}
	
	}

运行结果如下:

如何使用堆栈合成,利用栈实现四则运算代码C语言

你可以定义改变二维数组的长度和宽度,定义30、100等,都可以全部遍历完组合