前驱元素:若A元素在B元素的前面,则称A为B的前驱元素。
后继元素:若B元素在A元素的后面,则称B为A的后继元素
线性表的特征:数据元素之间具有一种一对一的逻辑关系。
1.第一个数据元素没有前驱,这个数据元素被称为头结点;
2.最后一个数据元素没有后继,这个数据元素被称为尾结点;
3.除了第一个元素和最后一个元素外,其他数据元素有且仅有一个前驱和一个后继。
线性表的分类:线性表中数据元素存储的方式可以是顺序存储,也可以是链式存储,按照不同的存储方式可分为顺序表和链表。
顺序表的API设计:
类名 | SequenceList |
---|---|
构造方法 | SequenceList(int capacity):创建容量为capacity的SequenceList对象 |
成员方法 | 1.public void clear():空置线性表 2.public boolean isEmpty():判断线性表是否为空,是返回true,不是返回false 3.public int length():返回线性表中的元素个数 4.public T get(int i):读取并返回线性表中的第i个元素的值 5.public void insert(int i,T t ):在线性表的第i个元素插入一个值为t的数据元素 6.public void insert(T t):在线性表中插入一个值为t的数据元素 7.public T remove(int i):删除并返回线性表中的第i个元素 8.public int indexOf(T t):返回线性表中首次出现指定的数据元素的位置,若不存在返回-1 |
成员变量 | 1.private T[] else:存储元素的数组 2.private int N :当前线性表的长度 |
代码实现:
public class SequenceList<T> {
private T[] eles;
private int N;
public SequenceList(int capacity){
this.eles = (T[])new Object[capacity];
this.N = 0;
}
public void clear(){
this.N = 0;
}
public boolean isEmpty(){
return N==0;
}
public int length(){
return N;
}
public T get(int i){
return eles[i];
}
public void insert(int i,T t ){
//先把i索引处的元素及后面的元素一次向后移动一位
for (int index = N-1;index > i;index--){
eles[index] = eles[index-1];
}
eles[i] = t;
N++;
}
public void insert(T t){
eles[N++] = t;
}
public T remove(int i){
T current = eles[i];
//索引i后的元素依次移动一位
for (int index = i; index < N-1; index++) {
eles[index] = eles[index+1];
}
N--;
return current;
}
public int indexOf(T t){
for (int i = 0; i < N; i++) {
if(eles.equals(t)){
return i;
}
}
return -1;
}
}
在java中,遍历集合的方式一般都使用的foreach循环,如果想让我们的SequenceList支持foreach循环,则需要:
1.让SequenceList实现Iterable接口,重写Iterable方法;
2.在SequenceList内部提供一个内部类SIterator,实现Iterator接口,重写hasNext方法和next方法;
代码实现:
import java.util.Iterator;
public class SequenceList<T> implements Iterable{
private T[] eles;
private int N;
public SequenceList(int capacity){
this.eles = (T[])new Object[capacity];
this.N = 0;
}
public void clear(){
this.N = 0;
}
public boolean isEmpty(){
return N==0;
}
public int length(){
return N;
}
public T get(int i){
return eles[i];
}
public void insert(int i,T t ){
//先把i索引处的元素及后面的元素一次向后移动一位
for (int index = N-1;index > i;index--){
eles[index] = eles[index-1];
}
eles[i] = t;
N++;
}
public void insert(T t){
eles[N++] = t;
}
public T remove(int i){
T current = eles[i];
//索引i后的元素依次移动一位
for (int index = i; index < N-1; index++) {
eles[index] = eles[index+1];
}
N--;
return current;
}
public int indexOf(T t){
for (int i = 0; i < N; i++) {
if(eles.equals(t)){
return i;
}
}
return -1;
}
@Override
public Iterator iterator() {
return new SIterator();
}
private class SIterator implements Iterator{
private int cusor;
public SIterator(){
this.cusor = 0;
}
@Override
public boolean hasNext() {
return cusor<N;
}
@Override
public Object next() {
return eles[cusor++];
}
}
}
1.添加元素时:
添加元素时,应该检查当前数组的大小是否能容纳新的元素,吐过不能容纳,则需要创建新的容量更大的数组。创建的新数组一般是原数组容量的2倍。
2.移除元素时:
移除元素时,应该检查当前数组的大小是否太大,比如正在用100个容量的数组存储10个元素,这样就会造成内存空间的浪费,应该创建一个容量更小的数组存储元素。如果发现数据元素不足数组容量的1/4,则创建一个是原数组容量的1/2的新数组存储元素。
代码实现:
import java.util.Iterator;
public class SequenceList<T> implements Iterable{
private T[] eles;
private int N;
public SequenceList(int capacity){
this.eles = (T[])new Object[capacity];
this.N = 0;
}
public void clear(){
this.N = 0;
}
public boolean isEmpty(){
return N==0;
}
public int length(){
return N;
}
public T get(int i){
return eles[i];
}
public void insert(int i,T t ){
if(N == eles.length){
resize(2*eles.length);
}
//先把i索引处的元素及后面的元素一次向后移动一位
for (int index = N-1;index > i;index--){
eles[index] = eles[index-1];
}
eles[i] = t;
N++;
}
public void insert(T t){
if(N == eles.length){
resize(2*eles.length);
}
eles[N++] = t;
}
public T remove(int i){
T current = eles[i];
//索引i后的元素依次移动一位
for (int index = i; index < N-1; index++) {
eles[index] = eles[index+1];
}
N--;
if(N < eles.length/4){
resize(eles.length/2);
}
return current;
}
public int indexOf(T t){
for (int i = 0; i < N; i++) {
if(eles.equals(t)){
return i;
}
}
return -1;
}
//根据参数newSize,重置eles的大小
public void resize(int newSize){
//定义一个临时数组,指向原数组
T[] temp = eles;
//创建新数组
eles = (T[])new Object[newSize];
//把原数组数据拷贝到新数组
for (int i = 0; i < N; i++) {
eles[i] = temp[i];
}
}
@Override
public Iterator iterator() {
return new SIterator();
}
private class SIterator implements Iterator{
private int cusor;
public SIterator(){
this.cusor = 0;
}
@Override
public boolean hasNext() {
return cusor<N;
}
@Override
public Object next() {
return eles[cusor++];
}
}
}
结点API设计:
类名 | Node |
---|---|
构造方法 | Node(T t,Node next):创建Node对象 |
成员变量 | T item:存储数据 Node next:指向下一个结点 |
代码实现:
public class Node {
//存储元素
public T item;
//指向下一个结点
public Node next;
public Node(T item,Node next){
this.item = item;
this.next = next;
}
}
生成链表:
public static void main(String[] args) throws Exception{
//构造结点
Node<Integer> first = new Node<Integer>(11,null);
Node<Integer> second = new Node<Integer>(13,null);
Node<Integer> third = new Node<Integer>(12,null);
Node<Integer> fourth = new Node<Integer>(8,null);
Node<Integer> fifth = new Node<Integer>(9,null);
//生成链表
first.next = second;
second.next = third;
third.next = fourth;
fourth.next = fifth;
}
单向链表是链表的一种,它由多个结点组成,每个结点都由一个数据域和一个指针域组成,数据域用来存储数据,指针域用来指向其后继结点。链表的头结点的数据域不存储数据,指针域指向第一个真正存储数据的结点。
类名 | LinkList |
---|---|
构造方法 | LinkList():创建LinkList对象 |
成员方法 | 1.public void clear():空置线性表 2.public boolean isEmpty():判断线性表是否为空,是返回true,否返回false 3.public int length():获取线性表中的元素个数 4.public T get(int i):读取并返回线性表中的第i个元素的值 5.public void insert(T t):往线性表中添加一个元素 6.public void insert(int i,T t):在线性表的第i个元素前插入一个值为t的数据元素 7.public T remove(int i):删除并返回线性表中的第i个数据元素 8.public int indexOf(T t):返回线性表中首次出现的指定的数据元素的位序号,若不存在返回-1 |
成员内部类 | private class Node:结点类 |
成员变量 | 1.pivate Node head:记录首结点 2.private int N:记录链表的长度 |
代码实现:
import java.util.Iterator;
public class LinkList<T> implements Iterable<T>{
private Node head;
private int N;
private class Node{
T item;
Node next;
public Node(T item,Node next){
this.item = item;
this.next = next;
}
}
public LinkList(){
//初始化头结点
this.head = new Node(null,null);
//初始化元素个数
this.N = 0;
}
public void clear(){
head.next = null;
this.N = 0;
}
public int length(){
return N;
}
public boolean isEmpty(){
return N==0;
}
public T get(int i){
//通过循环,从头结点开始,寻找i次,就可以找到对应元素
Node n = head.next;
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.item;
}
public void insert(T t){
//找到当前最后一个结点
Node n = head;
while(n.next != null){
n = n.next;
}
//创建新结点,保存元素t
Node newNode = new Node(t,null);
//让当前最后一个结点指向新结点
n.next = newNode;
//元素的个数+1
N++;
}
public void insert(int i,T t){
//找到i位置前一个结点
Node pre = head;
for (int index = 0; index < i-1; index++) {
pre = pre.next;
}
//找到i位置的结点
Node curr = pre.next;
//创建新结点,并且新结点需要指向原来i位置的结点
Node newNode = new Node(t,curr);
//原来i位置的前一个结点指向新结点
pre.next = newNode;
//元素的个数+1
N++;
}
public T remove(int i){
//先找到i位置的前一个结点
Node pre = head;
for (int index = 0; index < i-1; index++) {
pre = pre.next;
}
//找到i位置的结点
Node curr = pre.next;
//找到i位置的下一个结点
Node nextNode = curr.next;
//前一个结点指向下一个结点
pre.next = nextNode;
N--;
return curr.item;
}
public int indexOf(T t){
//遍历列表,取出item和t比较,如果相同则找出首次的结点位置
Node n = head;
for (int i = 0;n.next != null; i++) {
n=n.next;
if(n.item.equals(t)){
return i;
}
}
return -1;
}
@Override
public Iterator<T> iterator() {
return new LIterator();
}
private class LIterator implements Iterator{
private Node n;
public LIterator(){
this.n = head;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public Object next() {
n = n.next;
return n.item;
}
}
}
双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点豆油一个数据域和两个指针域组成,数据域用来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。链表的头结点的数据域不存储数据,指向前驱结点的指针域值为null,指向后继结点的指针域指向第一个真正存储数据的结点。
类名 | Node |
---|---|
构造方法 | Node(T t,Node pre,Node next):创建Node对象 |
成员变量 | T item:存储数据 Node next:指向下一个结点 Node pre:指向上一个结点 |
1.2.2.2双向链表API设计
类名 | TowWayLinkList |
---|---|
构造方法 | TowWayLinkList():创建TowWayLinkList对象 |
成员方法 | 1.public void clear():空置线性表 2.public boolean isEmpty():判断线性表是否为空,是返回true,否返回false 3.public int length():获取线性表中的元素个数 4.public T get(int i):读取并返回线性表中的第i个元素的值 5.public void insert(T t):往线性表中添加一个元素 6.public void insert(int i,T t):在线性表的第i个元素前插入一个值为t的数据元素 7.public T remove(int i):删除并返回线性表中的第i个数据元素 8.public int indexOf(T t):返回线性表中首次出现的指定的数据元素的位序号,若不存在返回-1 9.public T getFirst():获取第一个元素 10.public T getLast():获取最后一个元素 |
成员内部类 | private class Node:结点类 |
成员变量 | 1.private Node first:记录首结点 2.private Node last:记录尾结点 3.private int N:记录链表的长度 |
代码实现:
import java.util.Iterator;
public class TowWayLinkList<T> implements Iterable<T>{
private Node head;
private Node last;
private int N;
private class Node{
public Node(T item,Node pre,Node next){
this.item = item;
this.pre = pre;
this.next = next;
}
//存储数据
public T item;
//指向上一个结点
public Node pre;
//指向下一个结点
public Node next;
}
public TowWayLinkList(){
//初始化头结点和尾结点
this.head = new Node(null,null,null);
this.last = null;
this.N = 0;
}
public void clear(){
this.head.next = null;
this.last = null;
this.N = 0;
}
public int length(){
return N;
}
public boolean isEmpty(){
return N == 0;
}
public T getFirst(){
if(isEmpty()){
return null;
}
return head.next.item;
}
public T getLast(){
if(isEmpty()){
return null;
}
return last.item;
}
//插入元素
public void insert(T t){
//如果链表为空
if(isEmpty()){
//创建新结点
Node newNode = new Node(t,head,null);
//让新结点成为尾结点
last = newNode;
//让头结点指向尾结点
head.next = last;
}else{
Node newNode = new Node(t,last,null);
//让当前的尾结点指向新结点
last.next = newNode;
//让新结点成为尾结点
last = newNode;
}
N++;
}
//在指定位置处插入元素
public void insert(int i,T t){
//找到i位置的前一个结点
Node pre = head;
for (int index = 0; index < i; index++) {
pre = pre.next;
}
//找到i位置的结点
Node curr = pre.next;
//创建新结点
Node newNode = new Node(t,pre,curr);
//让i位置的前一个结点的下一个结点变为新结点
pre.next = newNode;
//让i位置的前一个结点变为新结点
curr.pre = newNode;
N++;
}
//获取指定位置i处的元素
public T get(int i){
Node n = head.next;
for (int index = 0; index < i; index++) {
n = n.next;
}
return n.item;
}
//找到元素t在链表中第一次出现的位置
public int indexOf(T t){
Node n = head;
for (int i = 0; n.next!=null ; i++) {
n = n.next;
if(n.next.equals(t)){
return i;
}
}
return -1;
}
//删除i位置的元素,并返回该元素
public T remove(int i){
//找到i位置的前一个结点
Node pre = head;
for (int index = 0; index < i; index++) {
pre = pre.next;
}
//找到i位置的结点
Node curr = pre.next;
//找到i位置的下一个结点
Node nextNode = curr.next;
//让i位置的前一个结点的下一个结点变为i位置的下一个结点
pre.next = nextNode;
//让i位置的下一个结点的上一个结点变为i位置的前一个结点
nextNode.pre = pre;
N--;
return curr.item;
}
@Override
public Iterator iterator() {
return new TIterator();
}
private class TIterator implements Iterator{
private Node n;
public TIterator(){
this.n = head;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public Object next() {
n = n.next;
return n.item;
}
}
}
链表反转的API设计:
public void reverse():对整个链表进行反转
public Node reverse(Node curr):反转链表中的某个结点curr,并把反转后的curr结点返回
使用递归可以完成反转,递归反转其实就是从原链表的第一个存数据的结点开始,依次递归调用反转每一个结点,知道把最后一个结点反转完毕,整个链表就反转完毕。
代码实现:
//用来反转整个链表
public void reverse(){
//判断当前链表是否为空链表,如果是空链表,则结束运行,如果不是,则调用重载的reverse方法完成反转
if(isEmpty()){
return;
}
reverse(head.next);
}
//反转指定的结点curr,并把反转后的结点返回
public Node reverse(Node curr){
if(curr.next == null){
head.next = curr;
return curr;
}
//递归的反转当前结点curr的下一个结点,返回值就是链表返回后,当前结点的上一个结点
Node pre = reverse(curr.next);
//让返回结点的下一个结点变为当前结点curr
pre.next = curr;
//把当前结点的下一个结点变为null
curr.next = null;
return curr;
}
}
快慢指针找中间值(链表):
public static String getMid(Node<String> first){
//定义两个指针
Node<String> fast = first;
Node<String> slow = first;
//使用两个指针遍历链表,当快指针指向的结点没有下一个结点结束循环
while(fast != null && fast.next != null){
//变换fast和slow的值
fast = fast.next.next;
slow = slow.next;
}
return slow.item;
}
快慢指针查找单向链表是否有环问题:
public static boolean isCirlce(Node<String> first){
//定义两个指针
Node<String> fast = first;
Node<String> slow = first;
//遍历列表,如果快慢指针指向同一个结点,则证明有环
while(fast != null && fast.next != null){
//变换fast和slow的值
fast = fast.next.next;
slow = slow.next;
if(fast.equals(slow)){
return true;
}
}
return false;
}
快慢指针查找有环链表入口问题:
public static Node getEntrance(Node<String> first){
//定义两个指针
Node<String> fast = first;
Node<String> slow = first;
Node<String> temp = null;
//遍历列表,先找到环,准备一个临时指针,指向链表的首结点,继续遍历,当慢指针与临时指针相遇的结点就是环入口
while(fast != null && fast.next != null){
//变换fast和slow的值
fast = fast.next.next;
slow = slow.next;
if(fast.equals(slow)){
temp = first;
continue;
}
//让临时结点变换
if(temp != null){
temp = temp.next;
//找出临时指针与慢指针相遇的位置
if(temp.equals(slow)){
break;
}
}
}
return temp;
}
栈是一种基于先进后出的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。
压栈:数据进入到栈的动作。
弹栈:数据从栈中出去的动作。
栈的API设计
类名 | Stack |
---|---|
构造方法 | Stackt():创建Stack对象 |
成员方法 | 2.public boolean isEmpty():判断栈是否为空,是返回true,否返回false 3.public int size():获取栈中的元素个数 4.public T pop(): 弹出栈顶元素 5.public void push(T t):向栈中压入元素 |
成员内部类 | private class Node:结点类 |
成员变量 | 1.pivate Node head:记录首结点 2.private int N:记录栈的元素个数 |
代码实现:
import java.util.Iterator;
public class Stack<T> implements Iterable<T> {
private Node head;
private int N;
private class Node{
public T item;
public Node next;
public Node(T item,Node next){
this.item = item;
this.next = next;
}
}
public Stack(){
this.head = new Node(null,null);
this.N = 0;
}
public boolean isEmpty(){
return N == 0;
}
public int size(){
return N;
}
//把T元素压入栈
public void push(T t){
//找到首结点指向的第一个结点
Node oldFirst = head.next;
//创建新结点
Node newNode = new Node(t,null);
//让首结点指向新结点
head.next = newNode;
//让新结点指向原来的第一个结点
newNode.next = oldFirst;
N++;
}
//弹出栈顶元素
public T pop() {
//找到首结点指向的第一个结点
Node oldFirst = head.next;
if (oldFirst == null) {
return null;
}
//让首结点指向原来第一个结点的下一个结点
head.next = oldFirst.next;
N--;
return oldFirst.item;
}
@Override
public Iterator<T> iterator() {
return new SIterator();
}
private class SIterator implements Iterator{
private Node n;
public SIterator(){
this.n = head;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public Object next() {
n = n.next;
return n.item;
}
}
}
//测试代码
import algorithm.linear.Stack;
public class Stacktest {
public static void main(String[] args) {
//创建栈对象
Stack<String> stack = new Stack<>();
//测试压栈
stack.push("a");
stack.push("b");
stack.push("c");
stack.push("d");
stack.push("e");
for (String item:stack
) {
System.out.println(item);
}
System.out.println("-------------------------------------------");
//测试弹栈
String result = stack.pop();
System.out.println("弹出的元素是"+result);
System.out.println("剩余元素个数"+stack.size());
}
}
问题描述:给定一个字符串,里面可能包含()小括号和其他字符,请编写程序检查该字符串的中的小括号是否成对出现
代码实现:
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.next();
boolean match = isMatch(s);
System.out.println(match);
}
public static boolean isMatch(String s){
//1.创建栈对象,用来存储左括号
Stack<String> chars = new Stack<>();
//2.从左往右遍历字符串
for (int i = 0; i < s.length(); i++) {
String currChar = s.charAt(i)+"";
//3.判断当前字符是否为左括号,如果是则把字符放入倒栈中
if(currChar.equals("(")){
chars.push(currChar);
}else if(currChar.equals(")")){
//4.继续判断当前字符是否有括号,如果是则从栈中弹出一个左括号,并判断弹出的结果是否为null,如果为null证明没有匹配的左括号,如果不为null,则证明有匹配的左括号
String pop = chars.pop();
if(pop == null){
return false;
}
}
}
//5.判断栈中还有没有剩余的左括号
if(chars.size() == 0){
return true;
}else{
return false;
}
}
}
中缀表达式:二元运算符总是置于两个操作数中间
逆波兰表达式(后缀表达式):运算符总是放在跟它相关的操作数之后
中缀表达式 | 逆波兰表达式 |
---|---|
a+b | ab+ |
a+(b-c) | abc-+ |
a+(b-c)*d | abc-d*+ |
a*(b-c)+d | abc-*d+ |
需求:给定一个只包含加减乘除四种运算的逆波兰表达式的数组表达方式,求出该逆波兰表达式的结果。
import java.util.Stack;
public class ReversePolishBitationTest {
public static void main(String[] args) {
//中缀表达式3*(17-15)+18/6的逆波兰表达式
String[] notation = {"3","17","15","-","*","18","6","/","+"};
int result = caculate(notation);
System.out.println("逆波兰表达式的结果为:"+result);
}
public static int caculate(String[] notaion){
//1.定义一个栈,用来存储操作数
Stack<Integer> oprands = new Stack<>();
//2.从左往右遍历逆波兰表达式,得到每一个元素
for (int i = 0; i < notaion.length; i++) {
String curr = notaion[i];
//3.判断当前元素式运算符还是操作数
Integer o1;
Integer o2;
Integer result;
switch (curr){
//4.运算符从栈中弹出两个操作数完成运算,运算完的结果再压入栈中
case "+":
o1 = oprands.pop();
o2 = oprands.pop();
result = o2 + o1;
oprands.push(result);
break;
case "-":
o1 = oprands.pop();
o2 = oprands.pop();
result = o2 - o1;
oprands.push(result);
break;
case "*":
o1 = oprands.pop();
o2 = oprands.pop();
result = o2 * o1;
oprands.push(result);
break;
case "/":
o1 = oprands.pop();
o2 = oprands.pop();
result = o2 / o1;
oprands.push(result);
break;
default:
//5.操作数把该操作数放入到栈中
oprands.push(Integer.parseInt(curr));
break;
}
}
//6.得到栈中最后一个元素,就是逆波兰表达式的结果
int result = oprands.pop();
return result;
}
}
队列是一种先进先出的数据结构,是一种只能在一端进行插入,在另一端进行删除操作的特许线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数据时先被取出。
队列的API设计:
类名 | Queue |
---|---|
构造方法 | Queue():创建Queue对象 |
成员方法 | 1.public boolean isEmpty():判断列表是否为空,是返回true,反之返回false 2.public int size():获取队列中元素的个数 3.public T dequeue():从队列中取出一个元素 4.public void enqueue(T t):往队列中插入一个元素 |
成员变量 | 1.private Node head:记录首结点 2.private int N:当前栈的元素个数 3.private Node last:记录最后一个结点 |
成员内部类 | private class Node:结点类 |
代码实现:
import java.util.Iterator;
public class Queue<T> implements Iterable<T>{
private Node head;
private Node last;
private int N;
private class Node{
public T item;
public Node next;
public Node(T item, Node next){
this.item = item;
this.next = next;
}
}
public Queue(){
this.head = new Node(null,null);
this.last = null;
this.N = 0;
}
public boolean isEmpty(){
return N==0;
}
public int size(){
return N;
}
//向队列中插入元素
public void enqueue(T t){
//当前尾结点last为null
if(last == null){
last = new Node(t,null);
head.next = last;
}else{
//当前尾结点last为null
Node oldlast = last;
last = new Node(t,null);
oldlast.next = last;
}
N++;
}
//从队列中取出一个元素
public T dequeue(){
if(isEmpty()){
return null;
}
Node oldfirst = head.next;
head.next = oldfirst;
N--;
//出队列其实在删除元素,因此如果对列中的元素被删除完后,需要重置last = null
if(isEmpty()){
last = null;
}
return oldfirst.item;
}
@Override
public Iterator<T> iterator() {
return new QIterator();
}
private class QIterator implements Iterator{
private Node n;
public QIterator(){
this.n = head;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public Object next() {
n = n.next;
return n.item;
}
}
}
//测试代码
import algorithm.linear.Queue;
public class Queuetest {
public static void main(String[] args) {
//创建队列对象
Queue<String> q = new Queue<>();
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");
q.enqueue("d");
q.enqueue("e");
for (String s: q
) {
System.out.println(s);
}
System.out.println("-------------------------------");
String result = q.dequeue();
System.out.println("出队列元素"+result);
System.out.println("剩余元素"+q.size());
}
}