使用单个数组实现三个堆栈

时间:2015-10-13 18:30:26

标签: java algorithm

针对这个问题调试一些解决方案,对于下面的代码片段,我认为方法pop()中的逻辑是错误的,因为在执行“indexUsed--”时,空格会被连续删除,但是当删除元素时,它不一定是连续的。

如果我错了,请随时纠正我。

int stackSize = 300;
int indexUsed = 0;
int[] stackPointer = { -1, -1, -1 };
StackNode[] buffer = new StackNode[stackSize * 3];
void push(int stackNum, int value) {
    int lastIndex = stackPointer[stackNum];
    stackPointer[stackNum] = indexUsed;
    indexUsed++;
    buffer[stackPointer[stackNum]] = new StackNode(lastIndex, value);
}
int pop(int stackNum) {
    int value = buffer[stackPointer[stackNum]].value;
    int lastIndex = stackPointer[stackNum];
    stackPointer[stackNum] = buffer[stackPointer[stackNum]].previous;
    buffer[lastIndex] = null;
    indexUsed--;
    return value;
}
int peek(int stack) { return buffer[stackPointer[stack]].value; }
boolean isEmpty(int stackNum) { return stackPointer[stackNum] == -1; }

class StackNode {
    public int previous;
    public int value;
    public StackNode(int p, int v) {
        value = v;
        previous = p;
    }
}

2 个答案:

答案 0 :(得分:2)

你是对的,这种方法不仅效率低,过于复杂,而且不正确

这是一个简单的测试来证明:

    StackArray stack = new StackArray();
    stack.push(0, 0);
    stack.push(1, 10);
    System.out.println(stack.pop(0));
    stack.push(1, 20);
    System.out.println(stack.pop(1));
    System.out.println(stack.pop(1));

产地:

 Exception in thread "main" java.lang.NullPointerException
   at StackArray.pop(StackArray.java:18)

堆栈数据结构通常实现为数组或单链表。链表的效率较低,因为它的元素分散在堆中,其元素也有内存开销(带指针的节点对象)。另一方面,数组更快,但它具有固定的大小,因此不能用于所有任务。

这些方法中的每一种都有其优点和缺点,但创建两种方法唯一缺点的混合方法绝对没有意义(具有固定容量和内存开销)。

如果这是一个合成任务,限制只使用一个数组来存储所有三个堆栈的元素,那么可以使用以下方法。

成对地逻辑分割数组元素。每对将代表单链表的一个节点。该对的第一个元素将保存该值,而第二个元素将是指向下一个节点的指针。

很清楚,数组可以容纳任意数量的独立单链表(只要它有足够的容量)并且你知道磁头的索引。

这个想法类似于描述中给出的方法,用于保存指向三个列表的头部的指针,但是(!)另外保持指向表示"空闲内存的列表的指针"并包括数组的所有非占用元素。最初这个"堆" list将包含数组的所有元素。当您将push元素放入其中一个堆栈时,需要pop中的heap元素并使用它来创建所需堆栈的元素。当元素从堆栈中popped时,此元素将pushed返回堆。

答案 1 :(得分:1)

您可以从阵列的一端启动其中一个堆栈。您可以从阵列的另一端启动另一个堆栈。你可以将第三个堆叠放在中间。当其中一个侧面堆栈需要空间时,您需要移动中间堆栈。但是,我有一个免费列表帮助的另一个实现。您也可以尝试此实现:

    public class ThreeStacksWithOneArray {

    //This is the stack node class
    class StackNode {
        //This is the value of the node
        int value;
        //This is showing the previous node
        int prev;
        //This is the constructor of the class
        StackNode(int value, int prev) {
            this.value = value;
            this.prev = prev;
        }
    }

    //This keeps the stack nodes
    private StackNode[] stackNodes = null;
    private static int CAPACITY = 10;
    //This keeps the top of free list
    private int freeListTop = 0;
    //This is the variable for the size
    private int size = 0;
    //These are the pointers to the three stacks
    private int[] stackPointers = { -1, -1, -1 };

    //This is the constructor of the main class
    ThreeStacksWithOneArray() {
        //Initialize the stack nodes
        stackNodes = new StackNode[CAPACITY];
        //initialize the free list
        initFreeList();
    }

    //Initialize the free list
    private void initFreeList() {
        for (int i = 0; i < CAPACITY; i++) {
            //The value of each node is 0 and it points to the next node
            stackNodes[i] = new StackNode(0, i + 1);
        }
    }

    //This is the push procedure
    public void push(int stackNum, int value) throws Exception {
        //Print the push information
        System.out.println("Push to stack "+stackNum+" value "+value);
        int freeIndex;
        int currentStackTop = stackPointers[stackNum - 1];
        //Find the free node
        freeIndex = getFreeNodeIndex();
        //Make a new node in the free index
        StackNode n = stackNodes[freeIndex];
        //Setting the previous node
        n.prev = currentStackTop;
        //Setting the value
        n.value = value;
        stackPointers[stackNum - 1] = freeIndex;
    }

    //This is the pop method
    public StackNode pop(int stackNum) throws Exception {
        //From which stack you want to pop. -1, since it starts from 0
        int currentStackTop = stackPointers[stackNum - 1];
        //This checks for stack underflow
        if (currentStackTop == -1) {
            throw new Exception("UNDERFLOW");
        }
        //Get the node as a temp node
        StackNode temp = stackNodes[currentStackTop];
        //Remove the node from stack
        stackPointers[stackNum - 1] = temp.prev;
        //Put this node as free node
        freeStackNode(currentStackTop);
        //Print the pop information
        System.out.println("Pop from stack "+stackNum+" value: "+temp.value);
        //Return the value
        return temp;
    }

    //Get a free node index
    private int getFreeNodeIndex() throws Exception {
        int temp = freeListTop;
        //Overflow
        if (size >= CAPACITY)
            throw new Exception("OVERFLOW");
        freeListTop = stackNodes[temp].prev;
        size++;
        //return the free node index
        return temp;
    }

    //Make one index free after a pop
    private void freeStackNode(int index) {
        stackNodes[index].prev = freeListTop;
        //Put the index in free list
        freeListTop = index;
        //Decrease the size by one
        size--;
    }

    public static void main(String args[]) {
        // Test Driver
        ThreeStacksWithOneArray mulStack = new ThreeStacksWithOneArray();
        try {
            //Adding to those three stacks
            mulStack.push(1, 11);
            mulStack.push(1, 12);
            mulStack.push(1, 13);
            mulStack.push(1, 14);
            mulStack.push(2, 21);
            mulStack.push(2, 22);
            mulStack.push(3, 31);
            mulStack.push(3, 32);
            //Popping from those three stacks
            mulStack.pop(1);
            mulStack.pop(2);
            mulStack.pop(3);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

有关详细信息,请访问:https://github.com/m-vahidalizadeh/foundations/blob/master/src/data_structures/ThreeStacksWithOneArray.java。我希望它有所帮助。