Data structure and algorithm series 4 queue

What is a queue

Queue is a special linear table. You can only enter the operation at both ends of the head and
tail. Rear : Only add elements from the end of the queue, called the
front of the queue : You can only take out or delete elements from the head of the queue. , Call out the team
first in first out principle: First in First out FIFO

It's like queuing in the cafeteria to buy food in our lives. The first ones buy the food first, and the later ones line up at the end of the line.

Insert picture description here

Queue interface design

int size(); //the number of elements
boolean(); //whether it is empty
void clear(); //clear the element
void enQueue(E element); //
Enqueue E deQueue(); //Dequeue
E front ();//Get the head element of the queue
**

Use linked lists to implement queues

LinkedList source code

package list;

import list.AbstractList;

public class LinkedList<E> extends AbstractList<E> {
	private Node<E> first;
	private Node<E> last;

	private static class Node<E> {
		E element;
		Node<E> prev;
		Node<E> next;
		public Node(Node<E> prev, E element, Node<E> next) {
			this.prev = prev;
			this.element = element;
			this.next = next;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();

			if (prev != null) {
				sb.append(prev.element);
			} else {
				sb.append("null");
			}

			sb.append("_").append(element).append("_");

			if (next != null) {
				sb.append(next.element);
			} else {
				sb.append("null");
			}

			return sb.toString();
		}
	}

	@Override
	public void clear() {
		size = 0;
		first = null;
		last = null;
	}

	@Override
	public E get(int index) {
		return node(index).element;
	}

	@Override
	public E set(int index, E element) {
		Node<E> node = node(index);
		E old = node.element;
		node.element = element;
		return old;
	}

	@Override
	public void add(int index, E element) {
		rangeCheckForAdd(index);

		// size == 0
		// index == 0
		if (index == size) { // 往最后面添加元素
			Node<E> oldLast = last;
			last = new Node<E>(oldLast, element, null);
			if (oldLast == null) { // 这是链表添加的第一个元素
				first = last;
			} else {
				oldLast.next = last;
			}
		} else {
			Node<E> next = node(index);
			Node<E> prev = next.prev;
			Node<E> node = new Node<E>(prev, element, next);
			next.prev = node;

			if (prev == null) { // index == 0
				first = node;
			} else {
				prev.next = node;
			}
		}

		size++;
	}

	@Override
	public E remove(int index) {
		rangeCheck(index);

		Node<E> node = node(index);
		Node<E> prev = node.prev;
		Node<E> next = node.next;

		if (prev == null) { // index == 0
			first = next;
		} else {
			prev.next = next;
		}

		if (next == null) { // index == size - 1
			last = prev;
		} else {
			next.prev = prev;
		}

		size--;
		return node.element;
	}

	@Override
	public int indexOf(E element) {
		if (element == null) {
			Node<E> node = first;
			for (int i = 0; i < size; i++) {
				if (node.element == null) return i;

				node = node.next;
			}
		} else {
			Node<E> node = first;
			for (int i = 0; i < size; i++) {
				if (element.equals(node.element)) return i;

				node = node.next;
			}
		}
		return ELEMENT_NOT_FOUND;
	}

	/**
	 * 获取index位置对应的节点对象
	 * @param index
	 * @return
	 */
	private Node<E> node(int index) {
		rangeCheck(index);

		if (index < (size >> 1)) {
			Node<E> node = first;
			for (int i = 0; i < index; i++) {
				node = node.next;
			}
			return node;
		} else {
			Node<E> node = last;
			for (int i = size - 1; i > index; i--) {
				node = node.prev;
			}
			return node;
		}
	}

	@Override
	public String toString() {
		StringBuilder string = new StringBuilder();
		string.append("size=").append(size).append(", [");
		Node<E> node = first;
		for (int i = 0; i < size; i++) {
			if (i != 0) {
				string.append(", ");
			}

			string.append(node);

			node = node.next;
		}
		string.append("]");
		return string.toString();
	}
}

Queue implementation

import com.sun.xml.internal.fastinfoset.util.ValueArrayResourceException;
import list.LinkedList;
import list.List;

public class Queue<E>{
    private List<E> list=new LinkedList<E>();
    //元素的数量
    public  int size (){
      return list.size();
    }
    //是否为空
    public  boolean isEmpty(){
        return list.isEmpty();
    }
    //清空元素
    public  void clear(){
        list.clear();
    }
    //入队
    public void enQueue(E element){
        list.add(element); ;
    }
    //出队
    public E deQueue(){
       return list.remove(0);
    }
    //获取队列的头元素
    public E front(){
        return list.get(0);
    }
}

Deque implementation

What is a deque

You can add and delete queues at the head and tail of the team

int size(); //元素的数量
boolean(); //是否为空
void clear();//清空元素
void enQueue(E element);//入队
E deQueue(); //出队
E front();//获取队列的头元素

The following methods are more than the original above methods

void enQueueRear(E element) //从队尾入队
E deQueeuRear() //从队尾出队
void enQueueFront() ///从队头入队
void rear(); //获取队尾元素

Dequeu source code implementation

The Linkedlist source code is the same as above

import list.LinkedList;
import list.List;

public class Deque<E> {

    private List<E> list=new LinkedList<E>();
    //元素的数量
    public  int size (){
        return list.size();
    }
    //是否为空
    public  boolean isEmpty(){
        return list.isEmpty();
    }
    //清空元素
    public  void clear(){
        list.clear();
    }
    //入队
    public void enQueue(E element){
        list.add(element); ;
    }
    //出队
    public E deQueue(){
        return list.remove(0);
    }
    //获取队列的头元素
    public E front(){
        return list.get(0);
    }
    /*从队尾入队*/
    public void enQueueRear(E element) {
        list.add(element);
    }
    /*从队尾出队*/
    public E deQueueRear() {
        return list.remove(list.size() - 1);
    }
     /*获取队尾元素*/
    public E rear() {
        return list.get(list.size() - 1);
    }
    /*从队头入队*/

    public void enQueueFront(E element){
        list.add(0,element);
    }
}

Circular queue

General introduction

The bottom layer of the queue can be implemented with an array and the optimized queue is also called a circular queue, that is, it can make full use of space without wasting resources

Insert picture description here

Delete an element
Insert picture description here

Add two elements and one element

Insert picture description here

There is no space behind the queue at this time, but there is still a space in front

Add an element
Insert picture description here

This is the general implementation of the circular queue, which is sufficient to ensure that the space of the array is not wasted

Source code implementation

import com.sun.org.apache.bcel.internal.generic.NEW;
import org.omg.IOP.ENCODING_CDR_ENCAPS;

import javax.print.DocFlavor;
import java.security.interfaces.ECKey;
import java.util.EventListener;

public class CircleQueue<E> {
    private int front;
    private int size;
    /*存储元素的数组*/
    private E[] elements;
    /*默认数组大小*/
    private static final int DEFAULT_CAPACITY = 10;
    /*构造方法*/
    public CircleQueue() {
        E[] es = (E[]) new Object[DEFAULT_CAPACITY];
    }
   //返回队列的大小
    public int size() {
        return size;
    }
   /*判断队列是否为空*/
    public boolean isEmpty() {
        return size == 0;
    }
    /*清除队列*/
    public void clear() {
        /*将数组元素设置为null*/
        for (int i = 0; i < size; i++) {
            elements[index(i)]=null;
        }
        /*头元素与size都置为0*/
        front=0;
        size=0;
    }
   /*元素入队*/
    public void enQueue(E element) {
        ensureCapacity(size+1);
        elements[index(size)]=element;
        size++;
    }
   /*元素出队*/
    public E deQueue() {
        /*保存队首元素*/
        E element = elements[front];
        /*队首元素置为null*/
        elements[front]=null;
        /*获取新的队首元素所在的地方*/
        front=(index(1));
        size--;
        return element;
    }
   /*获取头元素*/
    public E front() {
       return elements[front];
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        string.append("capcacity=").append(elements.length)
                .append(" size=").append(size)
                .append(" front=").append(front)
                .append(", [");
        for (int i = 0; i < elements.length; i++) {
            if (i != 0) {
                string.append(", ");
            }

            string.append(elements[i]);
        }
        string.append("]");
        return string.toString();
    }
    /*索引映射封装*/
    private int index(int index) {
     index+=front;
     return index-(index>= elements.length?elements.length:0);
    }

    /**
     * 保证要有capacity的容量
     * @param capacity
     */
    private void ensureCapacity(int capacity) {

        int oldCapacity = elements.length;
        if (oldCapacity>=capacity){
            int newCapacity=oldCapacity+(oldCapacity>>1);
            E[] newElements = (E[]) new Object[newCapacity];
            for (int i = 0; i < size; i++) {
                newElements[i]=elements[index(size)];
            }
            elements=newElements;
            front=0;
        }
    }
}

Key method

Index mapping encapsulation

It is a simple modulo operation, but I used the method of addition and subtraction to implement it here. Students who have learned the basics of computer systems know that this is more efficient. If the current index value + front value is greater than the current array length , Indicating that the value is at the front of the array

private int index(int index) {
     index+=front;
     return index-(index>= elements.length?elements.length:0);
    }

Array expansion

private void ensureCapacity(int capacity) {
		int oldCapacity = elements.length;
		if (oldCapacity >= capacity) return;
		
		// 新容量为旧容量的1.5倍
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		E[] newElements = (E[]) new Object[newCapacity];
		for (int i = 0; i < size; i++) {
			newElements[i] = elements[index(i)];
		}
		elements = newElements;
		
		// 重置front
		front = 0;
	}

Double-ended circular queue

package com.mj.circle;

@SuppressWarnings("unchecked")
public class CircleDeque<E> {
	private int front;
	private int size;
	private E[] elements;
	private static final int DEFAULT_CAPACITY = 10;
	
	public CircleDeque() {
		elements = (E[]) new Object[DEFAULT_CAPACITY];
	}
	
	public int size() {
		return size;
	}

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

	public void clear() {
		for (int i = 0; i < size; i++) {
			elements[index(i)] = null;
		}
		front = 0;
		size = 0;
	}

	/**
	 * 从尾部入队
	 * @param element
	 */
	public void enQueueRear(E element) {
		ensureCapacity(size + 1);
		
		elements[index(size)] = element;
		size++;
	}

	/**
	 * 从头部出队
	 * @param element
	 */
	public E deQueueFront() {
		E frontElement = elements[front];
		elements[front] = null;
		front = index(1);
		size--;
		return frontElement;
	}

	/**
	 * 从头部入队
	 * @param element
	 */
	public void enQueueFront(E element) {
		ensureCapacity(size + 1);
		
		front = index(-1);
		elements[front] = element;
		size++;
	}

	/**
	 * 从尾部出队
	 * @param element
	 */
	public E deQueueRear() {
		int rearIndex = index(size - 1);
		E rear = elements[rearIndex];
		elements[rearIndex] = null;
		size--;
		return rear;
	}

	public E front() {
		return elements[front];
	}

	public E rear() {
		return elements[index(size - 1)];
	}

	@Override
	public String toString() {
		StringBuilder string = new StringBuilder();
		string.append("capcacity=").append(elements.length)
		.append(" size=").append(size)
		.append(" front=").append(front)
		.append(", [");
		for (int i = 0; i < elements.length; i++) {
			if (i != 0) {
				string.append(", ");
			}
			
			string.append(elements[i]);
		}
		string.append("]");
		return string.toString();
	}
	
	private int index(int index) {
		index += front;
		if (index < 0) {
			return index + elements.length;
		}
		return index - (index >= elements.length ? elements.length : 0);
	}
	
	/**
	 * 保证要有capacity的容量
	 * @param capacity
	 */
	private void ensureCapacity(int capacity) {
		int oldCapacity = elements.length;
		if (oldCapacity >= capacity) return;
		
		// 新容量为旧容量的1.5倍
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		E[] newElements = (E[]) new Object[newCapacity];
		for (int i = 0; i < size; i++) {
			newElements[i] = elements[index(i)];
		}
		elements = newElements;
		
		// 重置front
		front = 0;
	}
}

Guess you like

Origin blog.csdn.net/pjh88/article/details/114495116