データ構造とアルゴリズムシリーズ4キュー

キューとは

キューは特殊な線形テーブルです。操作はヘッドと
テールの両端でのみ入力できます。リア:キューの
先頭と呼ばれるキューの最後からのみ要素を追加します。から要素を取り出したり削除したりすることのみができます。キューの先頭。、先入れ先出しの原則でチームを呼び出す
:先入れ先出しFIFO

食堂に並んで私たちの生活の中で食べ物を買うようなものです。最初の人が最初に食べ物を購入し、後の人が列の最後に並んでいます。

ここに画像の説明を挿入

キューインターフェイスの設計

int size(); //要素の数
boolean(); //空かどうかvoidclear(); //要素を
クリア
voidenQueue(E element); //
Enqueue E deQueue(); // Dequeue
E front(); //キューのhead要素を取得します
**

リンクリストを使用してキューを実装する

LinkedListソースコード

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

キューの実装

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の実装

dequeとは

チームの先頭と末尾でキューを追加および削除できます

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

以下の方法は、上記の元の方法よりも多くなります

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

Dequeuソースコードの実装

リンクリストのソースコードは上記と同じです

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

循環キュー

一般的な紹介

キューの最下層は配列で実装でき、最適化されたキューは循環キューとも呼ばれます。つまり、リソースを無駄にすることなくスペースを最大限に活用できます。

ここに画像の説明を挿入

要素を削除する
ここに画像の説明を挿入

2つの要素と1つの要素を追加します

ここに画像の説明を挿入

現時点では、キューの後ろにスペースはありませんが、前にスペースがあります

要素を追加する
ここに画像の説明を挿入

これは循環キューの一般的な実装であり、配列のスペースが無駄にならないようにするのに十分です。

ソースコードの実装

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;
        }
    }
}

キーメソッド

インデックスマッピングのカプセル化

単純なモジュロ演算ですが、ここでは足し算と引き算の方法を使って実装しました。コンピュータシステムの基礎を学んだ学生は、これがより効率的であることを知っています。現在のインデックス値+フロント値が現在よりも大きい場合配列の長さ、値が配列の先頭にあることを示します

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

配列拡張

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;
	}

両端循環キュー

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;
	}
}

おすすめ

転載: blog.csdn.net/pjh88/article/details/114495116
おすすめ