如何从链表中反转堆栈?

Posted

技术标签:

【中文标题】如何从链表中反转堆栈?【英文标题】:How can I reverse a Stack from a Linked List? 【发布时间】:2021-12-10 00:03:07 【问题描述】:

我正在开发一个使用链接列表中的堆栈的项目。我必须“实现一个包含测试器的堆栈。方法包括 push、pop、isEmpty 和 reverse。”我正在研究旨在反转堆栈的反向方法。但是,对于这种方法,我只允许“使用以下数据类型作为新变量:int、stack”。在这种方法中,我将我的 LinkedList 项目用于反向方法,但在这种情况下,我不允许这样做。有人知道我将如何反转堆栈吗?我的代码在下面。第一个代码段用于我的 LinkedList,第二个代码段用于我的 Stack 项目。

import java.util.Random;

public class LinkedListOfInts 
    Node head;
    Node tail;

    private class Node 
        int value;
        Node nextNode;

        public Node(int value, Node nextNode) 
            this.value = value;
            this.nextNode = nextNode;
        

    

    public LinkedListOfInts(int N, int low, int high) 
        Random random = new Random();
        for (int i = 0; i < N; i++)
            this.addToFront(random.nextInt(high - low) + low);
    

    public void addToFront(int x) 
        head = new Node(x, head);
        if (tail == null)
            tail = head;
    

    public int deleteFromFront() 
        int headValue = -1;
        if (head == null)
            return headValue;
        else 
            if (head == tail) 
                head = null;
                tail = null;
             else 
                headValue = head.value;
                head = head.nextNode;
            
        
        return headValue;
    

    public LinkedListOfInts reverse() 
        Node previous = null;
        Node current = head;
        Node next;
        while (current != null) 
            next = current.nextNode;
            current.nextNode = previous;
            previous = current;
            current = next;
        
        head = previous;
        return this;
    

    public String toString() 
        String result = "";
        for (Node ptr = head; ptr != null; ptr = ptr.nextNode) 
            if (!result.isEmpty()) 
                result += ", ";
            
            result += ptr.value;
        
        return "[" + result + "]";
    

    public static void main(String[] args) 
        LinkedListOfInts list = new LinkedListOfInts(5, 1, 10);
        System.out.println("Original List" + list.toString());
        list.addToFront(1);
        System.out.println("List After Adding One: " + list.toString());
        list.addToFront(2);
        System.out.println("List After Adding Two: " + list.toString());
        list.addToFront(3);
        System.out.println("List After Adding Three: " + list.toString());
        list.deleteFromFront();
        System.out.println("List After Deleting Item from the Front: " + list.toString());
        list.reverse();
        System.out.println("Reversed List: " + list.toString());

    


import java.util.Scanner;

public class Stack 
    LinkedListOfInts list = new LinkedListOfInts(5, 1, 10);

    public void push(int item) 
        list.addToFront(item);
    

    public int pop() 
        return list.deleteFromFront();
    

    public boolean isEmpty() 
        while (list.head != null) 
            list.head = null;
            return true;
        
        return false;
    

    public void reverse() 
        Stack tmpB = new Stack();
        while (!this.isEmpty()) 
            tmpB.push(this.pop());
        
        Stack tmpC = new Stack();
        while (!tmpB.isEmpty()) 
            tmpC.push(tmpB.pop());
        
        while (!tmpC.isEmpty()) 
            this.push(tmpC.pop());
        
    

    @Override
    public String toString() 
        return "Stack: " + list + "";
    

    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        Stack stack = new Stack();
        boolean done = false;
        while (!done) 
            System.out.println("1. Push");
            System.out.println("2. Pop");
            System.out.println("3. Empty");
            System.out.println("4. Reverse");
            System.out.println("5. toString");
            switch (input.nextInt()) 
            case 1:
                System.out.println("Add an Item to the Front of the Stack");
                stack.push(input.nextInt());
                break;
            case 2:
                System.out.println("Delete an Item at the Front of the Stack");
                System.out.println(stack.pop());
                break;
            case 3:
                System.out.println("Empty a Stack");
                System.out.println(stack.isEmpty());
                break;
            case 4:
                System.out.println("Reverse the List");
                stack.reverse();
                break;
            case 5:
                System.out.println("toString");
                System.out.println(stack.toString());
                break;
            
        
    

【问题讨论】:

提示:反转包含一个元素的堆栈很简单,什么都不做。现在只使用 push 和 pop,你如何反转恰好包含 2 个元素的堆栈? 你的程序运行得“不错”(也许除了“完成”部分;)!有什么问题? @xerx593 问题是我不应该使用“list.reverse();”相反,我应该写出代码,但我不确定如何写。我了解我必须做的事情的逻辑,但我什至不知道如何开始做堆栈的反向操作。 我认为这里的 (n) 任务是:将所有内容推入一个新的 (tmp) 堆栈,然后将其弹出回 this (list)。 我们会想到我会如何编写代码。我会写类似 Stack tmp = list.head; 的东西吗? ? 【参考方案1】:

好的,在澄清&修复方法之后:

// easiest method to "empty the stack":
public void clear() 
   this.list  = new LinkedListOfInts();


//method identifies, whether there are elements in the stack:
public boolean isEmpty() 
    return list.head == null;

..修复后:

public int deleteFromFront() 
    int headValue = -1;
    if (head == null)
        return headValue;
    else  //! move headValue(return value) assignment here, otherwise it returns -1 on 1-element lists.
        headValue = head.value;
        if (head == tail) 
            head = null;
            tail = null;
         else 
            head = head.nextNode;
        
    
    return headValue;

我们终于可以像这样欺骗了:

public void reverse() 
    Stack tmp = new Stack();
    while (!this.isEmpty()) 
        tmp.push(this.pop());
    
    this.list = tmp.list; // ;(;(

交付/享受,之后:

...
  case 3:
     System.out.println("Empty a Stack");
     stack.clear();
     System.out.println("Stack cleared!");
     break;
...
  case 6:
     System.out.println("bye!");
     done = true;
     break;

正如 Bohemian 提出的“纯堆栈”解决方案:

public void reverseStackOnly()  //works!+1^^
    Stack tmpB = new Stack();
    while (!this.isEmpty()) 
        tmpB.push(this.pop());
    
    Stack tmpC = new Stack();
    while (!tmpB.isEmpty()) 
        tmpC.push(tmpB.pop());
    
    while (!tmpC.isEmpty()) 
        this.push(tmpC.pop());
    

【讨论】:

当我反转堆栈时它是空的 您必须重命名isEmpty() 方法....(对不起!..请仔细阅读并应用答案) 即使在从 Bohemian 实施解决方案之后,反向方法也不起作用。我已经更正了上面的代码。 LinkedListOfInts 程序使用构造函数生成范围之间的随机整数列表。我在 Stack 程序中引用了该构造函数。当我尝试反转堆栈时,它是空的。堆栈中没有值。 一个名为“isBlahBlah”的方法应该做任何事!!! ..但只有检查(对于)“BlahBlah”! (详细!仔细!) 我不知道你是否意识到或关心,但这个 OP 正在使用多个帐户让其他人为他完成所有作业,包括编写他所有的代码。【参考方案2】:

仅使用堆栈操作的解决方案描述(不使用代码-由您编写,这是练习的重点):

要以相反的顺序创建新堆栈,请将每个元素从旧元素弹出推入新元素。

要反转堆栈,您需要清空它,然后以相同的顺序从堆栈中弹出推送。

因此,如果您想反转堆栈 A,请创建 2 个新堆栈 B 和 C。从 A->B 弹出推送,然后 B->C,然后 C->A。

【讨论】:

以上是关于如何从链表中反转堆栈?的主要内容,如果未能解决你的问题,请参考以下文章

反转链表中的每 k 个节点块

算法热门:反转单链表(LeetCode 206)解法二

剑指offer(十四,十五)链表中倒数第k个结点,反转链表

链表小题(反转链表 求倒数第k个结点 删除链表指定结点)

算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表删除排序链表中的重复元素

力扣——链表题 203.移除链表元素83.删除排序链表中重复元素82.删除排序链表中重复元素Ⅱ206.反转链表 876.链表的中间节点