Hands-on writing-stack, queue (Java implementation)

Stack interface design

1. Properties:

private List list; —— Use a linear table based on the List interface to implement the class design stack
2. Interface methods:

int size(); —— View the number of current stack elements
boolean isEmpty(); —— Determine whether the stack is empty
public void push(E element); —— Push the stack, add elements
public E pop(); —— Pop the stack , Delete the tail element
public E top(); —— add to get the top element of the stack
void clear(); —— clear the stack element
After the design is completed, the specific method coding is implemented, because the stack is implemented by using the dynamic array DynamicArray and the linked list LinkedList , All the encapsulated methods are called, so I won’t go into details here

Coding implementation
public class Stack extends DynamicArray{

//Using dynamic array to realize stack
private List list = new DynamicArray<>();

//Use the linked list to implement the stack
//private List list = new DynamicArray<>();

/**
* View the number of stack elements
* @return
*/
public int size() { return list.size(); }

/**
* Determine whether the stack is empty
* @return
*/
public boolean isEmpty() { return list.isEmpty(); }

/**
* Push into the stack, add elements
* @param element
*/
public void push(E element){ list.add(element); }

/**
* Pop the stack, delete the tail element
*/
public E pop(){ return list.remove(list.size()-1); }

/**
* Get the top element of the stack
* @return
*/
public E top(){ return list.get(list.size()-1); }

/**
* Clear stack elements
*/
public void clear() { list.clear(); } } Summary stack application




1. Double stack to realize the browser's forward and backward

2. Software Undo and Redo functions

Queue
concept
What is a queue?

Queue: The difference from the previous stack is that the stack can only operate on elements at the top end of the stack, while the queue can operate at both ends. The queue is also a special linear table.

Enqueue: You can only add elements from the rear of the queue, generally called enQueue

Dequeue: Elements can only be removed from the front of the queue, generally called deQueue

The structure of the queue

Compared with arrays, linked lists, and stacks, queues are also linear data structures that store the same type of data. The only difference is that queues are less restrictive than stacks, but larger than arrays and linked lists. For example, queues can only be in the queue. Add data at the tail end and remove elements at the head of the line. Based on this feature, the so-called "first in first out principle, First In First Out, FIFO" feature is available. The other two sides are closed in structural design, so the queue except The head element and other elements in the queue are unknown. Of course, the tail element is also visible, but we generally only add elements at the end of the queue, so this method will not be opened, and the queue cannot be accessed randomly. .

Graphical queue structure:

Insert picture description here

Queue design
Queue and array, linked list, and stack are all linear table structures, so we don’t need to do some repetitive operations. It is possible to use the previously written dynamic array DynamicArray and linked list LinkedList. The same can be done using stacks. The queue is implemented, but here we are using the doubly linked list Both_LinkedList.

As mentioned in the article “Hand-written List (Java Implementation)”, the head node and end node of a doubly linked list have first and last pointers. This is very convenient for operating elements at the head and end of the queue. Of course, it is used Dynamic arrays or singly linked lists are also possible, but deleting elements from the array at the head of the line will cause the subsequent element nodes to move forward, and when adding elements to the end of the singly linked list, the pointer head needs to traverse to the tail node. Both will increase the complexity, so it is better to choose a doubly linked list

The same, but the Queue we wrote does not directly inherit these classes, it is still implemented in a combined way, and draw the class diagram relationship

Insert picture description here

Queue interface design

1. Properties:

private List list; —— Use a linear table based on the List interface to implement class design queue
2. Interface method:

int size(); —— View the number of current queue elements
boolean isEmpty(); —— Determine whether the queue is empty
public void enQueue(E element); ——
Enqueue , add elements public E deQueue(); —— Dequeue , Delete the head element
public E front(); —— add to get the head element of the
queue void clear(); —— clear the queue element
After the design is completed, the specific method coding is implemented, because it is the queue implemented by the doubly linked list Both_LinkedList, call Are all encapsulated methods, I won’t go into details here

Coding implementation
Doubly linked list implementation queue:

public class Queue {

//Using the double-linked list encapsulation method to realize the queue
private List list = new Both_LinkedList<>();

/**
* Get the number of queue elements
* @return
*/
public int size() { return list.size(); }

/**
* Determine whether the current queue is empty
* @return
*/
public boolean isEmpty() { return list.isEmpty(); }

/**
* Join the queue, add elements from the end of the queue
* @param element
*/
public void enQueue(E element) { list.add(element); }

/**
* Dequeue, remove elements from the head of the queue
* @return
*/
public E deQueue() { return list.remove (0); }

/**
* Get the team head element
* @return
*/
public E front() { return list.get(0); }

/**
* Clear the queue elements
*/
public void clear() { list.clear(); } } Dual stack implementation queue:



public class QueueByStack {

//定义两个栈,inStack用于队尾入队,outStack用于队头出队
private Stack<E> inStack,outStack;

//使用构造函数初始化
public QueueByStack() {
    this.inStack = new Stack<>();
    this.outStack = new Stack<>();
}

/**
 * 获取队列元素数量
 * @return
 */
public int size() {
    return inStack.size() + outStack.size();
}

/**
 * 判断当前队列是否为空
 * @return
 */
public boolean isEmpty() {
    return inStack.isEmpty() && outStack.isEmpty();
}

/**
 * 入队,从队尾添加元素
 * @param element
 */
public void enQueue(E element) {
    inStack.push(element);
}

/**
 * 出队,从队头添加元素
 * @return
 */
public E deQueue() {
    checkOutStack();
    return outStack.pop();
}

/**
 * 获取队头元素
 * @return
 */
public E front() {
    checkOutStack();
    return outStack.top();
}

/**
 * 清空栈元素
 */
public void clear() {
    inStack.clear();
    outStack.clear();
}

/**
 * 检查outStack是否为空,如果不为空,等着出队
 * 如果为空,且inStack不为空,将inStack中的
 * 元素出栈,入栈到outStack,然后准备出队
 */
private void checkOutStack() {
    if (outStack.isEmpty()) {
        while (!inStack.isEmpty()) {
            outStack.push(inStack.pop());
        }
    }
}

}
Double-ended queue
concept
Double-ended queue: a queue that can be added and deleted at the head and tail ends

Structure diagram:

Insert picture description here

Design
There is no difference in the implementation relationship between Deque and Queue. It is also based on the doubly linked list Both_LinkedList and implemented using the combined mode.

Interface design of two-way queue

1. Properties:

private List list; —— Use a linear table based on the List interface to implement class design queue
2. Interface method:

int size(); —— View the number of current queue elements
boolean isEmpty(); —— Determine whether the queue is empty
public void enQueueRear(E element); —— Enqueue, enter the queue from the end
public E deQueueRear(); — —
Dequeue , from the end of the queue public void enQueueFront(E element); — Enqueue, from the head of the queue
public E enQueueFront(); — — Dequeue, from the head of the queue
public E front(); — — Add to get the head element
public E rear(); — Add to get the tail element
void clear(); — Clear the queue element
Code
public class Deque {

//利用双向链表封装好的方法实现队列
private List<E> list = new Both_LinkedList<>();

/**
 * 获取队列元素数量
 * @return
 */
public int size() {
    return list.size();
}

/**
 * 判断当前队列是否为空
 * @return
 */
public boolean isEmpty() {
    return list.isEmpty();
}

/**
 * 入队,从队尾入队
 * @param element
 */
public void enQueueRear(E element) {
    list.add(element);
}

/**
 * 出队,从队尾出队
 * @return
 */
public E deQueueRear() {
    return list.remove(list.size() - 1);
}

/**
 * 入队,从队头入队
 * @param element
 */
public void enQueueFront(E element) {
    list.add(0, element);
}

/**
 * 出队,从对头出队
 * @return
 */
public E deQueueFront() {
    return list.remove(0);
}

/**
 * 获取队头元素
 * @return
 */
public E front() {
    return list.get(0);
}

/**
 * 获取队尾元素
 * @return
 */
public E rear() {
    return list.get(list.size() - 1);
}

/**
 * 清空队列元素
 */
public void clear() {
    list.clear();
}

}
Circular queue
Circular queue
Concept:

Circular queue: the queue after implementation and optimization using an array

Graphic structure:

Insert picture description here

design:

The circular queue is also called the circular queue. It is implemented based on the Java array. The position pointed to by the front pointer is the head of the queue. In terms of design, after deleting an element, it will not be like an array. Move the element forward and overwrite it, but set the value empty. Move backward, delete the element with this mechanism, the position after the deletion, when the position behind the front pointer is full, the new element can fill in the empty space just deleted, playing the role of a circle

Loop interface design

1. Properties:

private int front; —— Circulation queue head pointer
private int size; —— Number of queue elements
private E[] elements; —— Use sequence structure array to store
private static final int DEFAULT_CAPACITY = 10; —— Default initialization value of array
2, Interface method:

int size(); —— View the number of current queue elements
boolean isEmpty(); —— Determine whether the queue is empty
public void enQueue(E element); —— Enqueue, enter the queue from the end of the queue
public E deQueue(); — — Dequeue, delete the head element
public E front(); — Add to get the head element of the
queue void clear(); — Clear the queue element
private void ensureCapacity(int capacity) — Ensure that there is a capacity of capacity, if not enough, expand the capacity
private int index(int ​​index); —— index mapping function, return real array subscript
1, dequeue operation

Insert picture description here

2. Join the team

3. Re-entry

Insert picture description here

4, Note:

(1) Join the team

Insert picture description here

(2) Join the team

Insert picture description here

(3) Departure

Insert picture description here

(4) Expansion

Insert picture description here

coding:

public class CircleQueue {

//数组的默认初始化值
private static final int DEFAULT_CAPACITY = 10;

//循环队列队头指针
private int front;

//队列元素数量
private int size;

//使用顺序结构数组存储
private E[] elements;

/**
 * 构造函数初始化数组
 */
public CircleQueue() {
    elements = (E[]) new Object[DEFAULT_CAPACITY];
}

/**
 * 获取队列元素的数量
 * @return
 */
public int size(){
    return size;
}

/**
 * 判断队列是否为空
 * @return
 */
public boolean isEmpty(){
    return size == 0;
}

/**
 * 入队,从队尾添加元素
 * @param element
 */
public void enQueue(E element) {
    ensureCapacity(size + 1);
    //elements[(front + size) % elements.length] = element;

    //调用封装函数
    elements[index(size)] = element;
    size++;
}

/**
 * 出队,从队头移除元素
 * @return
 */
public E deQueue() {
    E element = elements[front];
    elements[front] = null;
    //front = (front + 1) % elements.length;
    //调用封装函数
    front = index(1);
    size--;
    return element;
}


/**
 * 获取队头元素
 * @return
 */
public E front(){
    return elements[front];
}

/**
 * 清空队列元素
 */
public void clear() {
    for (int i = 0; i < size; i++) {
        //elements[(i + front) % elements.length] = null;

        //调用封装函数
        elements[index(i)] = null;
    }
    front = 0;
    size = 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[(i + front) % elements.length];

        //调用封装函数
        newElements[i] = elements[index(i)];
    }
    elements = newElements;

    // 重置front
    front = 0;
}

/**
 * 索引映射函数,返回真实数组下标
 * @param index
 * @return
 */
private int index(int index){
    return (front + index) % elements.length;
}

@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();
}

}
Circular deque
concept:

Circular double-ended queue: a circular queue that can be added and deleted at both ends

Graphic structure:

Insert picture description here

In fact, in structure, it is the same as the circular queue. There is no need to set a last pointer to point to the end of the queue, because we use the sequential storage structure of an array. In fact, last = (font + size-1)% array .length, it's just that we have extended its function in the method

Loop interface design

1. Properties:

private int front; —— Circulation queue head pointer
private int size; —— Number of queue elements
private E[] elements; —— Use sequence structure array to store
private static final int DEFAULT_CAPACITY = 10; —— Default initialization value of array
2, Interface method:

int size(); —— View the number of current queue elements
boolean isEmpty(); —— Determine whether the queue is empty
public void enQueueRear(E element); —— Enqueue, enter the queue from the end
public E deQueueRear(); — —
Dequeue , from the end of the queue public void enQueueFront(E element); — Enqueue, from the head of the queue
public E enQueueFront(); — — Dequeue, from the head of the queue
public E front(); — — Add to get the head element of the queue
public E rear(); —— Add to get the tail element of the
queue void clear(); —— Clear the queue element
private void ensureCapacity(int capacity) —— Ensure that there is a capacity capacity, if not enough, expand the
private int index (int index); - index mapping function returns true array subscript
coding

As mentioned above, the structure is the same as the circular queue, so most of the methods are the same, but its function is enhanced, and some method logic is adjusted.

Method changes:

(1) Add public void enQueueFront(E element); —— Enqueue, enter the queue from the head

/**

  • Join the team

  • @param element
    */
    public void enQueueFront(E element) {

    //front points to the previous position of the current node
    front = index(-1);
    //Assuming the virtual index, the position pointed to by front is 0, when adding elements to the head of the line, add elements to -1
    [front] = element;
    size++ ;
    }
    (2) Add public E deQueueRear(); —— dequeue, dequeue from the end of the queue

/**

  • Leave the team
  • @return
    */
    public E deQueueRear() { //Find the real index of the tail element int last = index(size-1); E element = elements[last]; elements[last] = null; size–; return element; } (3) Add public E rear(); —— Add to get tail elements







/**

  • Get the tail element
  • @return
    */
    public E rear() { return elements[index(size-1)]; } (4) Change private int index(int ​​index); —— index mapping function, return the real array index


/**

  • Index mapping function, returns the real array subscript

  • @param index

  • @return
    */
    private int index(int index){
    index += front;

    //But when the real index is 0, add an element to the head of the line and pass in -1, which is less than 0
    if (index <0){ index += elements.length; } return index% elements.length; } Longhua Avenue, No. 1 http ://www.kinghill.cn/LongHuaDaDao1Hao/index.html




Guess you like

Origin blog.csdn.net/weixin_45032957/article/details/108575317