棧和隊列的api設計及代碼實現

棧和隊列都是數據結構中最常見的結構,本篇我們使用java代碼的方式實現棧和隊列這兩種數據結構。

一、棧

1、棧的特點

棧的特點是先入後出,這是因爲棧的存取數據入口只有一個(用一個頭指針實現)。故先入棧的元素放入棧底部,後入棧的元素放到棧頂部。向棧中存入一個元素的操作叫做壓棧(push),從棧頂中取出一個元素的操作叫做彈棧(pop)。

2、棧的api設計

類名:Stack<T> (物理上基於鏈表)
構造方法: Stack()
成員方法:
public void push(T t) 向棧中放入一個元素
public T pop() 從棧中取出一個元素
public int size() 獲取長度
public boolean isEmpty() 判斷是否爲空

3、棧的java代碼實現

package com.tingcream.alg.linear;
 
import java.util.Iterator;
 
/**
 * 棧的api設計 (物理上採用鏈表來實現棧)
 */
public class Stack<T> implements  Iterable<T>{
    private Node head;//頭結點
    private int N;//鏈表長度
 
    //構造方法
    public Stack(){
        this.head=new Node(null,null);
        this.N=0;
    }
 
    //壓棧
    public void push(T t){
        //找到第一個節點
        Node<T> oldFirst=head.next;
        Node<T>  newNode=new Node(t,null);
        newNode.next=oldFirst;
        head.next=newNode;
 
        N++;
    }
 
    //彈棧
    public T pop(){
        Node<T> oldFirst=  head.next;
        if(oldFirst==null){
            return null ;
        }
        head.next=oldFirst.next;
        N--;
        return oldFirst.item;
    }
 
    //獲取長度
    public int size(){
        return this.N;
    }
    //判斷是否爲空
    public boolean isEmpty(){
        return this.N==0;
    }
    @Override
    public Iterator<T> iterator() {
        return new Itr();
    }
 
    private class Itr implements Iterator{
 
        private Node n;
 
        public Itr(){
            this.n=head;
        }
        @Override
        public boolean hasNext() {
            return n.next!=null;
        }
 
        @Override
        public Object next() {
            n=n.next; //n指針向後移動一步
            return n.item;
        }
    }
 
    private class Node<T> {
        private  T  item;
        private  Node next;
        public  Node(T item,Node next){
            this.item=item;
            this.next=next;
        }
    }
}

4、測試代碼

public class StackTest {
    public static void main(String[] args) {
        Stack<String> stack=new Stack<>();
        stack.push("a");
        stack.push("b");
        stack.push("c");
        stack.push("d");
        for(String s: stack){
            System.out.println(s);
        }
        System.out.println("============");
        String s1= stack.pop();
        System.out.println("彈出:"+s1);//d
        System.out.println("剩餘長度:"+stack.size());//3
    }
}

二、隊列

1、隊列的特點

隊列的特點是先入先出(FIFO) ,這是因爲隊列有兩個操作的入口(用頭指針和尾指針實現),頭指針由於插入新元素(入隊),尾指針用於取出元素(出隊)隊裏中插入新元素的操作叫做入隊(equeue),隊列中去除一個元素的操作叫做出隊(dequeue)

2、隊列的api設計

類名: Queue<T>   (物理上使用鏈表實現)
構造方法: Queue()
成員變量: 
private Node head 頭結點
private Node last 尾節點
private int N 鏈表數量
成員方法:
public void enqueue(T t)  入隊
public T dequeue() 出隊
public int size() 獲取長度
public boolean isEmpty() 判斷是否爲空

3、隊列的java代碼實現

package com.tingcream.alg.linear;
 
import java.util.Iterator;
 
/**
 * 隊列 (物理上使用鏈表實現)
 */
public class Queue<T> implements Iterable<T>{
    private Node head;//頭結點
    private Node last;//最後一個節點
    private int N;//鏈表數量
 
 
    public Queue(){
        this.head=new Node(null,null);
        this.last=null;
        this.N=0;
    }
 
    //隊列是否爲空
    public boolean isEmpty(){
        return this.N==0;
    }
    //隊列中元素數量
    public int size(){
        return this.N;
    }
 
    //入隊 加入一個元素
    public void enqueue(T t){
        //如果當前尾結點爲null,
        if(last==null){
            last=new Node(t,null);
            head.next=last;
        }else{
          // 當前尾結點不爲null
            Node oldLast=  last;
            last= new Node(t,null);
            oldLast.next=last;
        }
        N++;
 
    }
 
    //出隊  取出一個元素
    public T dequeue(){
       if(isEmpty()){
           return null;
       }
       Node<T> oldFirst=head.next;
       head.next=oldFirst.next;
       N--;
 
       //如果隊列中所有數據節點被刪除完了,需要重置last節點爲null
       if(isEmpty()){
           last=null;
       }
        return oldFirst.item ;
    }
 
 
 
    @Override
    public Iterator<T> iterator() {
        return new Itr();
    }
 
    //內部類 迭代器
    private  class Itr implements Iterator<T>{
        private Node<T> n;
 
        public Itr(){
            this.n=head;
        }
        @Override
        public boolean hasNext() {
            return n.next!=null;
        }
 
        @Override
        public T next() {
            n=n.next;//n指針向後移動一步
            return n.item;
        }
    }
 
 
 
    private class Node<T> {
        private  T  item;
        private  Node next;
        public  Node(T item,Node next){
            this.item=item;
            this.next=next;
        }
    }
 
}

4、測試代碼


import com.tingcream.alg.linear.Queue;


public class QueueTest {
    public static void main(String[] args) {
        Queue<String> queue=new Queue<String>();
        queue.enqueue("a");
        queue.enqueue("b");
        queue.enqueue("c");
        queue.enqueue("d");

        //由於Queue類中實現了iterator接口,故可以使用for遍歷
        for(String s:queue){
            System.out.println(s);
        }
        System.out.println("===========");

        String s1=queue.dequeue();
        String s2=queue.dequeue();

        System.out.println("s1:"+s1);//a
        System.out.println("s2:"+s2);//b
        System.out.println("剩餘元素個數:"+queue.size());//2個
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章