Stack_Queue 把栈排序 Sort a stack @CareerCup

原文:

Write a program to sort a stack in ascending order. You should not make any assumptions about how the stack is implemented. The following are the only functions that should be used to write this program: push | pop | peek | isEmpty.

译文:

写程序将一个栈按升序排序。对这个栈是如何实现的,你不应该做任何特殊的假设。 程序中能用到的栈操作有:push | pop | peek | isEmpty。


至少有四种方法:

1)借助另一个栈来排序:

另一个栈(有序栈)装排序完(从大到小)的结果。如何把无序栈的元素添加到有序栈呢?我们可以把下一个待插入的元素存放在一个临时变量toInsert里,然后在有序栈里,把所有比toInsert大的都倒腾到无序栈内。这样保证当toInsert插入有序栈时,toInsert以下的所有元素都小于它。然后继续处理下一个无序栈栈顶元素,最后直到无序栈中的所有元素都被转移到有序栈中!Time: O(N^2), Space: O(N)


2)如果可以用heap/priority queue,则就太简单了。

3) 可以在栈上进行merge sort。把当前栈的元素分到左右两个子栈,然后分别对两个子栈排序。最后是merge过程。不过要注意:栈只能从栈顶取元素,而左右栈已经是按从大到小排序好,所以要取出较大的元素压入stack,这样stack会变成从小到大排序,因此在merge的最后需要reverse stack!

4) 还可以在栈上进行quick sort。原理同merge sort


package Stack_Queue;

import java.util.Stack;

import CtCILibrary.AssortedMethods;

public class S3_6 {

	// 输入一个乱序的栈,返回一个排序过(栈顶最大,栈底最小)的栈
	// Time: O(N^2), Space: O(N)
	public static Stack<Integer> sort(Stack<Integer> stack) {
		Stack<Integer> sorted = new Stack<Integer>();
		while( !stack.isEmpty() ) {
			int toInsert = stack.pop();		// 先保存待处理的元素到一个临时变量
			while( !sorted.isEmpty() && sorted.peek() > toInsert ) {		// 把比toInsert大的元素都倒腾到stack
				stack.push(sorted.pop());
			}
			sorted.push(toInsert);			// 现在sorted栈顶元素已经小于toInsert,可以直接插入了
		}
		return sorted;
	}
	
	// mergeSort
	// Time: O(NlogN), Space: O(N)
	public static Stack<Integer> mergeSort(Stack<Integer> stack) {
		if ( stack.size() <= 1) {
			return stack;
		}
		
		Stack<Integer> left = new Stack<Integer>();
		Stack<Integer> right = new Stack<Integer>();
		
		int count = 0;
		while (stack.size() != 0) {
			count++;
			if (count % 2 == 0) {
				left.push(stack.pop());
			} else {
				right.push(stack.pop());
			}
		}
		
		left = mergeSort(left);
		right = mergeSort(right);
		
		// merge合并过程
		while ( left.size()>0 || right.size()>0 ) {
			if ( left.size() == 0 ) {	// 左栈为空,把右栈全部添加到stack
				stack.push(right.pop());
			} else if ( right.size() == 0 ) {	// 右栈为空为空,把左栈全部添加到stack
				stack.push( left.pop() );
			} 
			// 注意到栈只能从栈顶取元素,而左右栈已经是按从大到小排序好
			// 所以要取出较大的元素压入stack,这样stack会变成从小到大排序,
			// 因此在merge的最后需要reverse stack
			else if ( right.peek().compareTo(left.peek()) <= 0 ) {
				stack.push(left.pop());
			} else {
				stack.push(right.pop());
			}
		}
		
		Stack<Integer> reveseStack = new Stack<Integer>();
		while (stack.size() > 0 ) {
			reveseStack.push(stack.pop());
		}
		
		return reveseStack;
	}
	
	
	public static void main(String [] args) {
		Stack<Integer> s = new Stack<Integer>();
		
		for (int k = 1; k < 5; k++) {
				int r = AssortedMethods.randomIntInRange(0,  1000);
				s.push(r);
		}
		
//		s = sort(s);
		s = mergeSort(s);
		int last = Integer.MAX_VALUE;
		while(!s.isEmpty()) {
			int curr = s.pop();
			System.out.println(curr);
			if (curr > last) {
				System.out.println("Error: " + last + " " + curr);
			}
			last = curr;
		}
	}
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值