数据结构和算法分析数据结构与算法

栈系列之-原理与实现

2019-11-26  本文已影响0人  愤怒的谜团

一、栈的原理与特性

栈其实是一种特殊的线性表,因为栈只限定了一头进行增加和删除,其实这种应用场景还是蛮广的,比如递归操作,运算符匹配,只要是符合先进后出的队列都可以用栈来表达。因为限定了只能是一头进行增删,如果用顺序存储来实现,也减少了删除结点移动的带来的开销,所以栈如何能确定大小,使用顺序存储来实现也是高效的。


栈.png

因为栈是一种特殊的线性表,所以跟线性表一样都可以使用顺序存储和链式存储来实现。

二、栈顺序存储的实现-java

public class MyArrayStack {

    Object[] elemArray = null;
    int MaxLength; //stack的最大空间
    int top; //栈顶脚标

    // 使用顺序存储实现stack
    public MyArrayStack(int MaxLen){
        // 初始化一个stack
        this.MaxLength = MaxLen;
        top = -1; //因为数组的脚标初始为0,所以将top初始为-1
        elemArray = new Object[this.MaxLength];
    }

    /**
     * 栈常用方法如下:
     * 1、InitStack 初始化一个栈
     * 2、DestroyStack 若栈存在,则销毁该栈
     * 3、ClearStack 清空一个栈
     * 4、StackEmtry 判断一个栈是否为空
     * 5、GetTop 若栈存在,并且非空,返回栈顶元素
     * 6、push 若栈存在,往栈顶插入一个新的元素
     * 7、pop 若栈存在,并且非空,弹出栈顶元素
     * 8、StackLenth 若栈存在,返回该栈的长度
     */
    public void DestroyStack(){
        elemArray = null;
    }

    public Boolean ClearStack(){
        if (top == -1){return true;}
        for (int index = 0;index <= top;index++){
            //清空就是将数组每个值都置为null
            elemArray[index] = null;
        }
        top = -1;
        return true;
    }

    public Boolean StackEmtry(){
        return top == -1?true:false;
    }

    public Object GetTop(){
        if (top == -1 || elemArray == null){return false;}
        return elemArray[top];
    }

    public Boolean push(Object elem){
        if (top == MaxLength-1 || elemArray == null){return false;}
        elemArray[++top] = elem;
        return true;
    }

    public Object pop(){
         if (top == -1 || elemArray == null){return false;}
        Object elem = elemArray[top];
        elemArray[top] = null;
        top--;
        return elem;
    }

    public int StackLenth(){
        return elemArray.length;
    }

    public String toString(){
        if (top == -1 || elemArray == null){return "";}
        StringBuffer stringBuffer = new StringBuffer();
        for (int index = top;index > -1;index--){
            if (index-1>-1){
                stringBuffer.append(elemArray[index]);
                stringBuffer.append(",");
            }else{
                stringBuffer.append(elemArray[index]);
            }
        }
        return stringBuffer.toString();
    }

    public static void main(String[] args) {
    }
}

三、栈链式存储的实现-java

import java.util.Stack;

public class MyListStack {

    int currLength; //栈大小
    StackNode top; //栈顶指针,也是头结点

    class StackNode{
        Object nodeData; //结点值
        StackNode next; //指向下一个结点的引用
    }

    public MyListStack(){
        currLength = 0;
        top = new StackNode();
        top.nodeData = top.next = null; //初始化一个栈顶指针(头指针)
    }

    /**
     * 栈常用方法如下:
     * 1、InitListStack 初始化一个栈
     * 2、ClearListStack 清空一个栈
     * 3、ListStackEmtry 判断一个栈是否为空
     * 4、GetTop 若栈存在,并且非空,返回栈顶元素
     * 5、push 若栈存在,往栈顶插入一个新的元素
     * 6、pop 若栈存在,并且非空,弹出栈顶元素
     * 7、ListStackLenth 若栈存在,返回该栈的长度
     */

    public Boolean ClearListStack(){
        if (currLength == 0){return true;}
        else {
            StackNode nextNode = top.next;
            StackNode currNode = top;
            for (;currNode != null;currNode = currNode.next){
                currNode.next = null;
                currNode.nodeData = null;
                currNode = nextNode;
            }
            currLength = 0;
            return true;
        }
    }

    public Boolean ListStackEmtry(){
        return currLength == 0 ? true : false;
    }

    public Object GetTop(){
        if (currLength == 0){return false;}
        else{
            return top.nodeData;
        }
    }

    public Boolean push(Object elem){
        if (top.nodeData == null){
            //说明这是一个空栈
            top.nodeData = elem;
            currLength++;
            return true;
        }else{
            StackNode insertNode = new StackNode();
            insertNode.nodeData = elem;
            insertNode.next = top;
            top = insertNode;
            currLength++;
            return true;
        }
    }

    public Object pop(){
        if (currLength == 0){return false;}
        else{
            Object returnData = top.nodeData;
            top = top.next;
            currLength--;
            return returnData;
        }
    }

    public int ListStackLenth(){
        return currLength;
    }

    public String toString(){
        if (currLength == 0){return "";}
        else{
            StringBuffer stringBuffer = new StringBuffer();
            StackNode currNode = top;
            for (;currNode != null;currNode = currNode.next){
                if (currNode.next != null){
                    stringBuffer.append(currNode.nodeData);
                    stringBuffer.append(",");
                }else{
                    stringBuffer.append(currNode.nodeData);
                }
            }
            return stringBuffer.toString();
        }
    }

    public static void main(String[] args) {
    }
}

四、两种实现方式的差异

其实就是因为栈的特殊限制,使得stack的实现还是很简单的,因为只能在一头进行增删,所以不管是顺序实现还是链式实现,增删的时间复杂度都是O(1),栈只能查看栈顶元素,所以也跟增删一样,时间复杂度都是O(1)。如果能够确定大小,那么就可以使用顺序方式来实现栈,毕竟比链式方式更加节省空间,如果不能确定栈大小,那么还是使用链式方式来实现。普通栈只是一种特殊的线性表,还是属于基础的数据结构,可以用栈实现更加复杂的数据结构。

上一篇下一篇

猜你喜欢

热点阅读