用一个栈实现另一个栈的排序

题目:

一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈,除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?


方法一:

我用一个栈实现的,只有一个排序栈,和逆序一个栈思路一样,都是使用递归的方式记录局部变量,然后一个个压入栈中

getMaxElement()方法的目的是获取栈中从栈底到栈顶方法遇见的第一个最大值,然后把该元素弹出,其他栈中元素相对位置不变,把弹出的最大值作为返回值返回

pushMaxElement()方法的目的是不断获取到最大值,然后递归调用自身,然后再从最后获取到的最大值一个个压栈,最后栈中元素从大到小依次有序

package stack_queue;

import java.util.Stack;

/**
 * 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
 * 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
 * @author GPJ
 *
 */
public class SortStackByStack0 {
	Stack<Integer> s;
	boolean maxFlag;//在递归执行到栈底后,返回的过程中遇到的第一个跟返回的最大值相等的元素时,把该标志置为true,同时该元素不压栈
	public SortStackByStack0(){
		s = new Stack<Integer>();
		maxFlag = false;
	}
	//获取栈中最大元素,并把该元素从该栈中弹出,其他元素的相对位置不变
	public Integer getMaxElement(Integer max){
		if(s.isEmpty()) return max;
		Integer p = s.pop();
		if(p > max){
			max = p;
		}
		Integer returnMax = getMaxElement(max);
		if(!maxFlag && returnMax == p){//如果递归返回时,遇到第一个最大值时,不压栈。
			maxFlag = true;//maxFlag的作用是让递归返回时第一次遇见的最大值不压栈
			return returnMax;
		}
		s.push(p);
		return returnMax;
	}
	public void pushMaxElement0(){
		if(s.isEmpty()) return;
		maxFlag = false;
		int max = getMaxElement(Integer.MIN_VALUE);
		/*if(s.isEmpty()){
			s.push(max);
			return;
		}*/
		pushMaxElement0();
		s.push(max);
	}
	
	public static void main(String[] args) {
		SortStackByStack0 sb = new SortStackByStack0();
		sb.s.push(5);
		sb.s.push(1);
		sb.s.push(2);
		sb.s.push(5);
		
		//sb.s.push(1);
		//sb.s.push(-5);
		//sb.s.push(2);
		//sb.s.push(4);
		sb.pushMaxElement0();
		
		System.out.println(sb.s.pop());
		System.out.println(sb.s.pop());
		System.out.println(sb.s.pop());
		System.out.println(sb.s.pop());
		
	}
}

方法二:

getMaxElement()方法的目的同样是获取最大值,只不过是使用两个栈实现的,不使用递归,只是使用两个栈相互之间出栈入栈,与弹出的栈进行比较,从而获取到最大值,同时保证其他的元素相对位置不变

pushMaxElement()功能跟方法一一样,同样是使用递归方式进行局部变量的保存,在递归返回时依次入栈

package stack_queue;

import java.util.Stack;

/**
 * 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
 *  除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
 * 
 * @author GPJ
 *
 */
public class SortStackByStack1 {
	Stack<Integer> s0;
	Stack<Integer> s1;

	public SortStackByStack1() {
		s0 = new Stack<Integer>();
		s1 = new Stack<Integer>();
	}

	public Integer getMaxElement() {
		int max = s0.pop();
		if(s0.isEmpty()){return max;}
		Integer pop;
		while (!s0.isEmpty()) {
			pop = s0.pop();
			if (max > pop) {
				s1.push(pop);
			} else {
				s1.push(max);
				max = pop;
			}
		}
		while(!s1.isEmpty()){
			s0.push(s1.pop());
		}
		return max;
	}
	
	public void pushMaxElement(){
		if(s0.isEmpty()) return;
		Integer max = getMaxElement();
		pushMaxElement();
		s0.push(max);
	}
	
	public static void main(String[] args) {
		SortStackByStack1 sb = new SortStackByStack1();
		sb.s0.push(4);
		sb.s0.push(2);
		sb.s0.push(-5);
		sb.s0.push(1);

		sb.pushMaxElement();
		
		System.out.println(sb.s0.pop());
		System.out.println(sb.s0.pop());
		System.out.println(sb.s0.pop());
		System.out.println(sb.s0.pop());
	}
}

方法三:

只使用了一个方法实现,sortStackElement()方法目的就是排序栈s中的元素,没有使用递归,只是每一次for循环都获取到一个最小值,同时使用一个count进行标志,表示下次for循环需要循环多少次,已经获取最小值并压入到栈底的元素不用进行比较排序了

package stack_queue;

import java.util.Stack;

/**
 * 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
 *  除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
 * 
 * @author GPJ
 *
 */
public class SortStackByStack2 {
	Stack<Integer> s0;

	public SortStackByStack2() {
		s0 = new Stack<Integer>();
	}

	public void sortStackElement(Stack<Integer> s) {
		int count = 0;
		while(!s.isEmpty()){//计算栈中元素个数
			s0.push(s.pop());
			count++;
		}
		while(!s0.isEmpty()){//把s0中的元素压入到栈s中
			s.push(s0.pop());
		}
		
		Integer min;
		Integer val;
		while(count != 0){
			 min = s.pop();
			//获取最小值,栈s中的元素出栈,即把栈s中从栈顶往下的count-1个元素出栈(因为已经min=s.pop()了一个元素了),入栈到s0中
			for(int i = 0; i < count - 1; i++){
				val = s.pop();
				if(min > val){
					s0.push(min);
					min = val;
				}else{
					s0.push(val);
				}
			}
			s.push(min);//把最小值放到栈s的下面
			while(!s0.isEmpty()){//把栈s0中的所有元素全部压入s中
				s.push(s0.pop());
			}
			count--;
		}
	}
	public static void main(String[] args) {
		SortStackByStack2 sb = new SortStackByStack2();
		Stack<Integer> s = new Stack<Integer>();
		s.push(4);
		s.push(2);
		s.push(-5);
		s.push(1);
		sb.sortStackElement(s);
		
		System.out.println(s.pop());
		System.out.println(s.pop());
		System.out.println(s.pop());
		System.out.println(s.pop());
	}
}

标准答案:

使用了两个栈和一个变量,把排序栈中的第一个元素压入辅助栈中,然后如果排序栈中新弹出的cur元素比辅助栈的元素大的话,就把辅助栈中的元素压回排序栈,把cur元素压入辅助栈中。不断重复此过程,辅助栈中的元素始终是从小到大排序。

最后把辅助栈中的元素依次压入排序栈中,结束。

其中用到了栈的特性,当把元素压入栈中,在次压回另一个栈,相对顺序是不变的。

package stack_queue;

import java.util.Stack;

/**
 * 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
 * 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
 * @author GPJ
 *
 */
public class SortStackByStack {
	public static void sortStackByStack(Stack<Integer> stack){
		Stack<Integer> help = new Stack<Integer>();
		while(!stack.isEmpty()){
			int cur = stack.pop();
			while(!help.isEmpty() && help.peek() < cur){
				stack.push(help.pop());
			}
			help.push(cur);
		}
		while(!help.isEmpty()){
			stack.push(help.pop());
		}
	}
	public static void main(String[] args) {
		Stack<Integer> stack = new Stack<Integer>();
		stack.push(4);
		stack.push(2);
		stack.push(-5);
		stack.push(1);
		
		sortStackByStack(stack);
		
		System.out.println(stack.pop());
		System.out.println(stack.pop());
		System.out.println(stack.pop());
		System.out.println(stack.pop());
	}
}

我自己的实现的比较的时间复杂度无论是最好还是最坏情况都是平方级别,而标准答案的最好情况的比较的时间复杂度是线性级别,但是最坏情况是立法级别,所以标准答案适合整体有序的的情况,而且标准答案的方法的实现很好的应用了栈的特性,我的三个方法实质是一种思路,只不过把递归实现改为循环实现,本质是一样的。

注:

其中我的实现为了方便都是在类中成员变量的形式实现的,其实是应该以方法传参实现,只是把方法多加一个参数,其他的实现完全一样,没有区别。




在C++中,我们可以使用标准模板库(STL)中的`stack`容器来实现的基本操作,并通过某种算法来实现的混洗甄别。这里我们先假设混洗是指随机打乱中元素顺序,而甄别则是检查这个是否保持了排序的特性(例如升序或降序)。以下是一个简单的例子,我们将创建一个函数`shuffleSortStack`来进行的混洗和排序: ```cpp #include <iostream> #include <stack> #include <random> #include <algorithm> // 定义一个辅助函数,用于比较元素的大小(这里以升序为例) bool compare(int a, int b) { return a <= b; } // 混洗并排序 void shuffleSortStack(std::stack<int>& stack) { // 首先,复制内容到一个数组 std::vector<int> elements(stack.size()); while (!stack.empty()) { elements.top() = stack.pop(); } // 使用随机化算法打乱数组 std::random_device rd; // 获取随机数源 std::mt19937 g(rd()); // Mersenne Twister随机数生成器 std::shuffle(elements.begin(), elements.end(), g); // 然后,将元素回填到中,并保持排序 for (int i : elements) { if (i != stack.top()) { // 如果不是当前最大值,就入 while (!stack.empty() && !compare(stack.top(), i)) { stack.pop(); // 移除大于新元素的元素 } stack.push(i); // 将新元素放到合适的位置 } else { // 当找到相等的元素,直接添加到顶 stack.push(i); } } } int main() { std::stack<int> s = {5, 2, 8, 1, 9}; // 初始化一个整数 std::cout << "Original Stack: "; while (!s.empty()) { std::cout << s.top() << " "; s.pop(); } std::cout << "\n"; shuffleSortStack(s); std::cout << "Sorted and Shuffled Stack: "; while (!s.empty()) { std::cout << s.top() << " "; s.pop(); } std::cout << "\n"; return 0; } ``` 这个程序首先创建了一个整数,然后使用`shuffleSortStack`函数将其混合并保持升序。运行结果会展示出混洗后保持有序的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值