栈与队列

Posted swen3252

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈与队列相关的知识,希望对你有一定的参考价值。

最近一直在看数据结构与算法,下面是对有线性结构的栈与队列的总结:

栈相关的内容

定义:栈是限定仅在表尾进行插入和删除操作的线性表。(后进先出的线性表)

操作:在可以插入与删除的一端称为栈顶,另外一端称为栈底, 栈的插入称为进栈,栈的删除称为出栈。

图解:A,B,C依次入栈,然后依次出栈得到C,B,A 如图所示:

技术分享图片

栈的存储结构:栈通常有顺序栈和链栈两种存储结构

1. 顺序存储结构:通过数组实现,只准栈顶进出元素,不过由于数组的大小是事先确定的,而且需要连续的空间,当容量不过时需要手动扩展。

java实现代码:

public class Stack {
    private int maxSize; // size of stack array
    private double[] stackArray;
    private int top;     // top of stack
    public Stack(int s) // constructor
    {
        maxSize = s;     // set array size
        stackArray = new double[maxSize]; // create array
        top = -1;         // no items yet
    }
    public void push(double j) // put item on top of stack
    {
        stackArray[++top] = j; // increment top, insert item
    }
    public double pop()         // take item from top of stack
    {
        return stackArray[top--]; // access item, decrement top
    }
    public double peek()         // peek at top of stack
    {
        return stackArray[top];
    }
    public boolean isEmpty()    // true if stack is empty
    {
        return (top == -1);
    }
    public boolean isFull()     // true if stack is full
    {
        return (top == maxSize-1);
    }
}
class StackApp{
    public static void main(String[] args){
        Stack theStack = new Stack(10); // make new stack
        theStack.push(20);                 // push items onto stack
        theStack.push(40);
        theStack.push(60);
        theStack.push(80);
        while( !theStack.isEmpty() ){   // delete item from stack
            double value = theStack.pop();
            System.out.print(value);    // display it
            System.out.print(" ");
        }                                 // end while
        System.out.println("");
    } 
} 
//the result:80.0 60.0 40.0 20.0
?

 2.链式存储结构:通过链表实现,最大的优点是存储空间不固定可以伸缩。 

class Link{
    public double dData;   // data item
    public Link next;      // next link in list

    public Link(double dd){// constructor 
        dData = dd;
    }

    public void displayLink(){ // display ourself
        System.out.print(dData + " "); 
    }
} // end class Link
class LinkList{
    private Link first;  // ref to first item on list
    public LinkList(){   // constructor
        first = null;
    }                    // no items on list yet
    public boolean isEmpty(){ // true if list is empty
        return (first==null);
    }
    public void insertFirst(double dd){ // insert at start of list     
        Link newLink = new Link(dd);  // make new link
        newLink.next = first;      // newLink --> old first
        first = newLink;         // first --> newLink
    }
    public double deleteFirst(){  // delete first item
        Link temp = first;     // save reference to link
        first = first.next;       // delete it: first-->old next
        return temp.dData;        // return deleted link
    }
    public void displayList(){
        Link current = first;         // start at beginning of list
        while(current != null)        // until end of list,
        {
            current.displayLink();    // print data
            current = current.next;   // move to next link
        }
        System.out.println("");
    }
}                                     // end class LinkList
class LinkStack
{
    private LinkList theList;
    public LinkStack(){               // constructor    
        theList = new LinkList();
    }
    public void push(double j){       // put item on top of stack
        theList.insertFirst(j);
    }
    public double pop(){              // take item from top of stack
        return theList.deleteFirst();
    }
    public boolean isEmpty(){         // true if stack is empty
        return ( theList.isEmpty() );
    }
    public void displayStack(){
        System.out.print("Stack (top-->bottom): ");
        theList.displayList();
    }
}                                    // end class LinkStack
class LinkStackApp
{
    public static void main(String[] args) throws IOException{
        LinkStack theStack = new LinkStack(); // make stack
        theStack.push(20);          // push items
        theStack.push(40);
        theStack.displayStack();    // display stack
        theStack.push(60);          // push items
        theStack.push(80);
        theStack.displayStack();    // display stack
        theStack.pop();             // pop items
        theStack.pop();
        theStack.displayStack();    // display stack
    }                              // end main()
}
//the result:
//Stack (top-->bottom): 40.0 20.0 
//Stack (top-->bottom): 80.0 60.0 40.0 20.0 
//Stack (top-->bottom): 40.0 20.0
?
队列相关的内容
?

定义:只允许在一端进行插入操作,而在另一端进行删除操作的线性表。(先进先出的线性表)

操作:可以插入的一端称为队尾,可以删除的一端称为队头,栈的插入称为入队,栈的删除称为出队。

图解:

技术分享图片

队列的存储结构:队列通常也有顺序和链式两种存储结构

1. 顺序存储结构:

我们在队尾进行插入,在队头进行删除,因此必须保证队头元素在数组下标为0的位置处,故要将队列中的每个元素向前移动一个位置

技术分享图片

此时,会有涉及到一个问题,即性能问题,在队尾插入一个元素,不需要移动任何元素,时间复杂度是O[1],但是在队头删除一个元素,要队列中所有的元素都要向前移动一个位置,确保下标为0的位置不为空,时间复杂度是O[n],如果我们不限定出队操作时所有的元素都要向前移动,即通过移动front,rear来控制队头与队尾所在的位置。

如图,我删除队头元素a0,然后自增front,将a1作为新的队头,则可以免去移动队列中元素所带来的性能损耗。

技术分享图片

然后此时,新的问题产生了,即假溢出,就是front一直增加时间,直到rear没有位置进行插入,队尾入队已经满了。图如下:

技术分享图片

于是引入了循环队列,后面满了,就从头再开始,也就是头尾相接的循环,这种头尾相接的顺序存储结构称为循环队列。

技术分享图片

注意:因为用的是数组,所以还会面临一个数组溢出的问题。

java实现代码:

class Queues
{
    private int maxSize;
    private int[] queArray;
    private int front;
    private int rear;
    public Queues(int s){     // constructor    
        maxSize = s+1;         // array is 1 cell larger
        queArray = new int[maxSize]; // than requested
        front = 0;
        rear = -1;
    }
    public void insert(int j){     // put item at rear of queue    
        if(rear == maxSize-1)
        rear = -1;
        queArray[++rear] = j;
    }
    public int remove(){         // take item from front of queue    
        int temp = queArray[front++];
        if(front == maxSize)
        front = 0;
        return temp;
    }
    public int peek(){             // peek at front of queue    
        return queArray[front];    
    }
    public boolean isEmpty(){     // true if queue is empty    
        return ( rear+1==front || (front+maxSize-1==rear) );
    }
    public boolean isFull(){     // true if queue is full    
        return ( rear+2==front || (front+maxSize-2==rear) );
    }
    public int size(){             // (assumes queue not empty)    
        if(rear >= front)         // contiguous sequence
        return rear-front+1;
        else                     // broken sequence
        return (maxSize-front) + (rear+1);
    }
} // end class Queue

class QueueApp
{
    public static void main(String[] args)
    {
        Queues theQueue = new Queues(5); // queue holds 5 items
        theQueue.insert(10);              // insert 4 items
        theQueue.insert(20);
        theQueue.insert(30);
        theQueue.insert(40);
        theQueue.remove();                  // remove 3 items
        theQueue.remove();                  // (10, 20, 30)
        theQueue.remove();
        theQueue.insert(50);              // insert 4 more items
        theQueue.insert(60);              // (wraps around)
        theQueue.insert(70);
        theQueue.insert(80);
        while( !theQueue.isEmpty() )      // remove and display
        {                                  // all items
            int n = theQueue.remove();   // (40, 50, 60, 70, 80)
            System.out.print(n);
            System.out.print(" ");
            }
            System.out.println("");
        }                                  // end main()
}                                          // end class QueueApp
//the result:40 50 60 70 80
?

2.链式存储结构:通过线性表中的单链表经行实现,尾进头出。

技术分享图片

技术分享图片

代码:

class Link
{
    public double dData;         // data item
    public Link next;            // next link in list
    public Link(double d){       // constructor
        dData = d;
    }
    public void displayLink(){  // display this link
        System.out.print(dData + " ");
    }
}                                // end class Link
class FirstLastList{
    private Link first;         // ref to first item
    private Link last;          // ref to last item
    public FirstLastList(){     // constructor
        first = null;           // no items on list yet
        last = null;
    }
    public boolean isEmpty(){   // true if no links
        return first==null;
    }
    public void insertLast(double dd){ // insert at end of list
        Link newLink = new Link(dd);   // make new link
        if( isEmpty() )                // if empty list,
        first = newLink;               // first --> newLink
        else
        last.next = newLink;           // old last --> newLink
        last = newLink;                // newLink <-- last
    }
    public double deleteFirst(){       // delete first link
        double temp = first.dData;
        if(first.next == null)         // if only one item
        last = null;                   // null <-- last
        first = first.next;            // first --> old next
        return temp;
    }
    public void displayList(){
        Link current = first;        // start at beginning
        while(current != null){      // until end of list,
            current.displayLink();   // print data
            current = current.next;  // move to next link
        }
        System.out.println("");
    }
}                                    // end class FirstLastList
class LinkQueue
{
    private FirstLastList theList;
    public LinkQueue(){                // constructor
        theList = new FirstLastList(); // make a 2-ended list
    }
    public boolean isEmpty(){          // true if queue is empty
        return theList.isEmpty();
    }
    public void insert(double j){      // insert, rear of queue
        theList.insertLast(j);
    }
    public double remove(){            // remove, front of queue
        return theList.deleteFirst();
    }
    public void displayQueue(){
        System.out.print("Queue (front-->rear): ");
        theList.displayList();
    }
}                                    // end class LinkQueue
class LinkQueueApp
{
    public static void main(String[] args) throws IOException{
        LinkQueue theQueue = new LinkQueue();
        theQueue.insert(20);         // insert items
        theQueue.insert(40);

        theQueue.displayQueue();     // display queue
        theQueue.insert(60);         // insert items
        theQueue.insert(80);
        theQueue.displayQueue();     // display queue
        theQueue.remove();           // remove items
        theQueue.remove();
        theQueue.displayQueue();     // display queue
    }                                // end main()
}                                    // end class LinkQueueApp
//the result:
//Queue (front-->rear): 20.0 40.0 
//Queue (front-->rear): 20.0 40.0 60.0 80.0 
//Queue (front-->rear): 60.0 80.0
?

 

以上是关于栈与队列的主要内容,如果未能解决你的问题,请参考以下文章

栈与队列:循环队列算法+可执行代码

[算法] leetcode栈与队列相关题目详解

数据结构《三》栈与队列的实现

栈与队列试题中的操作代码

从今天开始好好学数据结构02栈与队列

数据结构栈与队列