1.
スタック
(スタック)
1.1コンセプト
スタック:一方の固定端でのみ要素の挿入と削除を可能にする特別な線形リスト。データの挿入と削除が実行される一方の端はスタックの最上位と呼ばれ、もう一方の端はスタックの最下部と呼ばれます。スタック内のデータ要素は、LIFO
(
後入れ先出し
)の原則に従います。
プッシュスタック:スタックの挿入操作はプッシュ
/
プッシュ
/プッシュと呼ばれ
、プッシュされ
たデータはスタックの最上位にあります
。
ポップ:スタックの削除はポップと呼ばれます。
出力データはスタックの一番上にあります。
1.2実装
1.シーケンステーブルを使用して、テール挿入
+
テール削除の方法を使用します。
2.
リンクリストを使用して達成すると、頭と尾の両方が
比較的言えば、シーケンステーブルの実装は単純なので、スタックを実装するためにシーケンステーブルを使用することをお勧めします。
配列ベースのシーケンシャルスタック、実装コードは次のとおりです。
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 基于数组的顺序栈实现
* @param <E>
*/
public class MyStack<E> {
// 当前栈的数据个数
private int size;
// 实际存储数据的动态数组 - ArrayList
private List<E> data=new ArrayList<>();
//入栈
public void push(E val){
//尾插
data.add(val);
size++;
}
//出栈,并返回栈顶元素
public E pop(){
if(isEmpty()){
// 栈为空,没有栈顶元素
throw new NoSuchElementException("stack is empty! cannot pop!");
}
// 删除栈顶元素
E val = data.remove(size - 1);
size --;
return val;
// 等同于 return data.remove(--size);
}
//只返回栈顶元素
public E peek(){
if(isEmpty()){
// 栈为空,没有栈顶元素
throw new NoSuchElementException("stack is empty! cannot peek!");
}
return data.get(size-1);
}
//判断栈是否为空
public boolean isEmpty(){
return size == 0;
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
sb.append(data.get(i));
if(i!=size-1){
// 此时还没到栈顶,还没到数组末尾
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
参照方法は次のとおりです。
public class StackTest {
public static void main(String[] args) {
MyStack<Integer> stack=new MyStack<>();
stack.push(1);
stack.push(2);
stack.push(3);
//打印栈所有元素
System.out.println(stack);
//打印栈顶元素
System.out.println(stack.peek());
//出栈,并打印栈顶元素
stack.pop();
System.out.println(stack);
}
}
上記の入力結果に基づくと、次のようになります。
2.
キュー
_
2.1コンセプト
キュー:一方の端でのデータ挿入操作ともう一方の端での削除データ操作のみを許可する特別な線形テーブル。キューには、first-in-first-out(FIFO)(First In First Out)エントリキューがあります。挿入操作は、キューからのキューのテール(テール/リア)と呼ばれます。削除操作の終了は、キューの先頭と呼ばれます。
先入先出
2.2実装
キューは、配列とリンクリストの構造で実装することもできます。配列の構造を使用すると、データの先頭でのデキューと出力の効率が向上するため、リンクリストの構造を使用することをお勧めします。アレイは比較的低くなります。
リンクリストに基づいて実装された基本キュー、実装コードは次のとおりです。
インターフェイスクラス:
public interface IQueue<E> {
// 入队
void offer(E val);
//出队
E poll();
//返回队首元素
E peek();
//判断队列是否为空
boolean isEmpty();
}
キュークラス:
import stack_queue.queue.IQueue;
import java.util.NoSuchElementException;
/**
* 基于链表实现的基础队列
* @param <E>
*/
public class MyQueue<E> implements IQueue<E> {
// 链表的每个节点
private class Node{
E val;
Node next;
public Node(E val){
this.val=val;
}
}
// 当前队列中的元素个数
private int size;
// 队首
private Node head;
//队尾
private Node tail;
@Override
public void offer(E val) {
Node node=new Node(val);
if(head==null){
// 此时链表为空
head=tail=node;
}else {
tail.next=node;
tail=node;
}
size++;
}
@Override
public E poll() {
if(isEmpty()){
throw new NoSuchElementException("queue is empty! cannot poll");
}
Node node=head;
head=node.next;
// 将原来头节点脱钩
node.next=null;
size--;
return node.val;
}
@Override
public E peek() {
if(isEmpty()){
throw new NoSuchElementException("queue is empty! cannot peek");
}
return head.val;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("[");
// 链表的遍历
for(Node x=head;x!=null;x=x.next){
sb.append(x.val);
if(x.next!=null){
// 还没走到链表尾部
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
参照方法は次のとおりです。
import stack_queue.queue.impl.MyQueue;
public class QueueTest {
public static void main(String[] args) {
IQueue iQueue=new MyQueue();
iQueue.offer(1);
iQueue.offer(2);
iQueue.offer(3);
System.out.println(iQueue);
System.out.println(iQueue.peek());
iQueue.poll();
System.out.println(iQueue);
}
}
上記の入力結果に基づくと、次のようになります。