数据结构- 栈 & 队列

226 阅读3分钟

栈(Stack)

分为顺序结构和链表结构 特点:先进后出,后进先出

顺序结构

存储线性表的数据元素的方式 = 一段地址连续的存储单元

在类的内部使用数组来存储元素,数组的大小会根据需要动态的变化,因为有一个resize()方法,使用N来表示栈顶的上面一个位置,入栈时,先将元素放入data[N],N再进行加一的操作;反之,出栈时,先将N减一,取出元素,再置此时data[N]的值为nul

public class ArrayStack<Item> implements Iterable<Item> {

    private Item[] data = (Item[]) new Object[1]; // 栈里的数据
    private int N = 0; // 栈的元素个数

    public boolean isEmpty(){
        return N==0;
    }

    public int length(){
        return N;
    }

    public void resize(int len){
        Item[] temp = (Item[]) new Object[len];
        for (int i=0; i<N; i++){
            temp[i] = data[i];
        }
        data = temp;
    }

    public void push(Item item){
        if (N == data.length){
            this.resize(2* data.length);
        }
        data[N++] = item;
    }

    public Item pop(){
        Item item = data[--N];
        data[N] = null; // 避免对象游离
        if (N>0 && N==data.length/4){
            this.resize(data.length/2);
        }
        return item;
    }

    @Override
    public Iterator<Item> iterator() {
        return new ReverseArrayIterator();
    }

    // 内部类
    public class ReverseArrayIterator implements Iterator<Item>{
        private int i = N;

        public boolean hasNext(){
            return i>0;
        }

        public Item next(){
            return data[--i];
        }

        public void remove(){

        }
    }

    public static void main(String[] args) {
        ArrayStack<Integer> testStack = new ArrayStack<>();
        testStack.push(1);
        testStack.push(2);
        testStack.push(3);
        testStack.push(4);
        for (Integer i:testStack){
            System.out.println(i);
        }
        testStack.pop();
        for (Integer i:testStack){
            System.out.println(i);
        }
    }
}

链式结构

结构特点 存储线性表的数据元素的方式 = 一段地址不连续、任意的存储单元 ​ 设定一个top指针表示栈顶,所以显然当top为null时,表示栈空。入栈:新建一个oldTop变量指向此时的top指向,再让top指向新插入的元素结点,再设其next指针指向oldTop;出栈:只需在取出元素之后让栈顶指针指向下一个元素即可

public class Stack<Item> implements Iterable<Item> {
    private Node top;
    private int N;

    private class Node{
        Item item;
        Node next;

        public Node(Item item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    public boolean isEmpty(){
        return top==null;
    }

    public int length(){
        return N;
    }

    public void push(Item item){
        Node oldTop = top;
        top = new Node(item,oldTop);
        N = N + 1;
    }

    public Item pop(){
        Item item = top.item;
        top = top.next;
        return item;
    }

    @Override
    public Iterator<Item> iterator() {
        return new StackIterator();
    }

    private class StackIterator implements Iterator<Item>{

        private Node current = top;

        @Override
        public boolean hasNext() {
            return current != null;
        }

        @Override
        public Item next() {
            Item item = current.item;
            current = current.next;
            return item;
        }
    }
}

队列

特点:先进先出

顺序队列

特点:使用一组地址连续的内存单元依次保存数据,也可以定义一个特定大小的结构数组作为队列

public class CirQueue {
    private Object[] objs;
    private int front = 0;// 头指针
    private int rear = 0;// 尾指针
    private int size;// 空间大小
    private int length = 0;

    // 初始化
    public CirQueue(int size) {
        this.size = size;
        objs = new Object[size];
    }

    // 计算长度(即队列元素个数)
    public int getLength() {
        return length;
    }

    // 判空
    public boolean isEmpty() {
        if (front == rear) {
            return true;
        }
        return false;
    }

    // 判满
    public boolean isFull() {
        if ((rear + 1) % size == front) {
            return true;
        }
        return false;
    }

    // 入队
    public boolean enQueue(Object n) {
        if (isFull()) {
            return false;
        }
        rear = (rear + 1) % size;// 体现循环
        objs[rear] = n;
        length++;
        return true;
    }

    // 出队
    public Object deQueue() {
        Object n = null;
        if (!isEmpty()) {
            front = (front + 1) % size;// 体现循环
            n = objs[front];
            objs[front] = null;
            length--;
        }
        return n;
    }

    // 输出
    public void show() {
        for (Object obj : objs) {
            if (obj == null) {
                System.out.print("空   ");
            } else {
                System.out.print(obj.toString() + "  ");
            }
        }
        System.out.println("");
    }
}

链式队列

public class QueueLink implements Queue {
 
    // 定义一个节点内部类
    class Node {
        private Object data;
        private Node next;
 
        public Node(Object obj) {
 
            this.data = obj;
 
        }
 
        public Node() {
             
        }
 
    }
 
    // 定义链式队列的一些属性
    private Node head; // 头指针(引用)
    private Node rear; // 尾指针(引用)
    private int length; // 队列的长度,开始为1
    private Node temp; // 临时指针(引用)
 
    // 初始化队列,空头指针
    public QueueLink() {
        head = new Node();
        rear = head;
        length = 1;
 
    }
 
    // 初始化队列,有数据头指针
    public QueueLink(Object obj) {
        head = new Node(obj);
        rear = head;
        length = 1;
    }
 
    public boolean clear() {
        // TODO Auto-generated method stub
        if(this.length==1){
             
            return true;
        }else if(length==2){
             
            head.next=null;
            //没有引用的节点java会自动回收内存
             
        }else {
             
            while(head.next.next!=null){
                head.next=head.next.next;
                 
                 
            }
             
            head.next=null;
            return true;
             
        }
        return false;
         
         
         
    }
 
    // 判空
    public boolean isEmpty() {
        // TODO Auto-generated method stub
 
        if (this.length() == 1) {
 
            return true;
        } else {
 
            return false;
        }
    }
 
    // 获得队列的长度
    public int length() {
        // TODO Auto-generated method stub
        return this.length;
    }
 
    // 添加一个节点
    public void offer(Object x) {
        this.temp = new Node(x);
 
        // 队列使用尾插法
        rear.next = temp;
        rear = temp;
        this.length++;
 
        // TODO Auto-generated method stub
 
    }
 
    // 查看第一个节点
    public Node peek() {
        // TODO Auto-generated method stub
        if (length == 1) {
 
            temp=null;
        } else {
 
            temp= head.next;
        }
        return temp;
    }
    //删除第一个节点
    public Node poll() {
        // TODO Auto-generated method stub
         
         
        if(length==1){
            //无法删除
            temp=null;
             
        }else
         
        if(length==2){
            this.temp= head.next;
            //置空下一个节点就可以了
            head.next=null;
            length--;
             
        }else{
            this.temp= head.next;
            this.head.next=this.head.next.next;
            length--;
        }
         
         
         
        return temp;
    }
    //test
    public static void main(String[] args) {
        QueueLink linkQueue = new QueueLink();
        System.out.println("队列是否为空:"+linkQueue.isEmpty());
        System.out.println("连续入队-------------------------------");
        for(int i=0;i<5;i++){
            linkQueue.offer((char)(97+i));
        }
        System.out.println("队列长度为:"+linkQueue.length());
        System.out.println("队首元素为:"+linkQueue.peek().data);
  
        //出队
        System.out.println("连续出队-------------------------------");
        for(int i=0;i<4;i++){
            Object data=linkQueue.poll();
        }
        System.out.println("队列长度为:"+linkQueue.length());
         
    }
 
}