0 课程地址
https://coding.imooc.com/lesson/207.html#mid=13450
1 重点关注
1.1 代码草图解析
1.2 使用链表实现队列代码解析
见3.1
1.3 链表生成的队列和动态数组生成的循环队列 性能比较 代码解析
见3.3
2 课程内容
3 Coding
3.1 使用链表实现栈代码解析 关键代码
public LinkedListQueue(){ size = 0; head = null; tail = null; } /** * 链表尾进行入队 * @author weidoudou * @date 2022/10/30 18:09 * @param e 请添加参数描述 * @return void **/ @Override public void enQueue(E e) { if(tail==null){ tail = new Node(e); head = tail; }else{ tail.next = new Node(e); tail = tail.next; } size++; } /** * 链表首进行出队,(因为相比较而言链表尾不容易出队,链表尾出队的话,倒数第二个node无法取到) * @author weidoudou * @date 2022/10/30 18:02 * @return E **/ @Override public E deQueue() { if(isEmpty()){ throw new IllegalArgumentException("队列为空,无法出队"); } Node retNode = head; head = head.next;//注意这里用head.next 而不要用retNode.next retNode.next = null; //这里遗漏了,如果head变成null了,说明链表已经为空了,需要把tail也置为空 if(head==null){ tail = null; } size--; return retNode.e; } @Override public E getFront() { if(size==0){ throw new IllegalArgumentException("队列为空,无法查看队列顶元素"); } return head.e; }
3.2 使用链表实现栈代码解析 全量代码
- 实现类:
package com.company; /** * 由于链表只能在一端进行操作,而队列可以在两端操作,先进先出,所以定义栈顶head和栈底tail比较方便O(1)操作 * @author weidoudou * @date 2022/10/30 16:43 * @return null **/ public class LinkedListQueue<E> implements Queue<E>{ /** * 1 内部类node * @author weidoudou * @date 2022/10/28 7:59 * @return null **/ private class Node{ //Node 只有两个属性,下一个节点和本节点存储的元素 private E e; private Node next; /** * 通用调用node方法 * @author weidoudou * @date 2022/10/28 8:17 * @param e 请添加参数描述 * @param next 请添加参数描述 * @return null **/ public Node(E e,Node next){ this.e = e; this.next = next; } /** * node 无参构造 * @author weidoudou * @date 2022/10/28 8:15 * @return null **/ public Node(){ this(null,null); } /** * node 有参构造 * @author weidoudou * @date 2022/10/28 8:16 * @param e 请添加参数描述 * @return null **/ public Node(E e){ this(e,null); } @Override public String toString() { return e.toString(); } } private int size; private Node head,tail; public LinkedListQueue(){ size = 0; head = null; tail = null; } /** * 链表尾进行入队 * @author weidoudou * @date 2022/10/30 18:09 * @param e 请添加参数描述 * @return void **/ @Override public void enQueue(E e) { if(tail==null){ tail = new Node(e); head = tail; }else{ tail.next = new Node(e); tail = tail.next; } size++; } /** * 链表首进行出队,(因为相比较而言链表尾不容易出队,链表尾出队的话,倒数第二个node无法取到) * @author weidoudou * @date 2022/10/30 18:02 * @return E **/ @Override public E deQueue() { if(isEmpty()){ throw new IllegalArgumentException("队列为空,无法出队"); } Node retNode = head; head = head.next;//注意这里用head.next 而不要用retNode.next retNode.next = null; //这里遗漏了,如果head变成null了,说明链表已经为空了,需要把tail也置为空 if(head==null){ tail = null; } size--; return retNode.e; } @Override public E getFront() { if(size==0){ throw new IllegalArgumentException("队列为空,无法查看队列顶元素"); } return head.e; } @Override public int getSize() { return size; } @Override public boolean isEmpty() { return size==0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("LinkedListQueue:front "); Node cur = head; while (cur!=null){ sb.append(cur+"->"); cur=cur.next; } sb.append("Null tail"); return sb.toString(); } }
- 接口:
package com.company; /** * 队列接口 * @author weidoudou * @date 2022/10/23 11:10 * @return null **/ public interface Queue<E> { /** * 循环队列入队 队尾插入元素 * @author weidoudou * @date 2022/10/23 11:10 * @param e 请添加参数描述 * @return void **/ void enQueue(E e); /** * 循环队列出队 队首删除元素 * @author weidoudou * @date 2022/10/23 11:11 * @return E **/ E deQueue(); /** * 队首展示元素 * @author weidoudou * @date 2022/10/23 11:11 * @return E **/ E getFront(); /** * 获取size * @author weidoudou * @date 2022/10/23 11:12 * @return int **/ int getSize(); /** * 是否为空 * @author weidoudou * @date 2022/10/23 11:12 * @return boolean **/ boolean isEmpty(); }
- 测试类:
public static void main(String[] args) { Queue<Integer> queue = new LinkedListQueue<>(); for(int i = 0;i<10 ;i++){ queue.enQueue(i); System.out.println(queue); if(i%3==0){ queue.deQueue(); System.out.println(queue); } } }
- 测试结果:
LinkedListQueue:front 0->Null tail LinkedListQueue:front Null tail LinkedListQueue:front 1->Null tail LinkedListQueue:front 1->2->Null tail LinkedListQueue:front 1->2->3->Null tail LinkedListQueue:front 2->3->Null tail LinkedListQueue:front 2->3->4->Null tail LinkedListQueue:front 2->3->4->5->Null tail LinkedListQueue:front 2->3->4->5->6->Null tail LinkedListQueue:front 3->4->5->6->Null tail LinkedListQueue:front 3->4->5->6->7->Null tail LinkedListQueue:front 3->4->5->6->7->8->Null tail LinkedListQueue:front 3->4->5->6->7->8->9->Null tail LinkedListQueue:front 4->5->6->7->8->9->Null tail Process finished with exit code 0
3.3 链表生成的队列和动态数组生成的循环队列 性能比较 代码解析
- 测试类:
public static void main(String[] args) { int count = 1000000; //循环数组队列 Queue<Integer> loopQueue = new LoopQueue<>(); //数组队列 Queue<Integer> linkedListQueue = new LinkedListQueue<>(); double time1 = getLinkedListAndArray(linkedListQueue,count); System.out.println("linkedListQueue time1==="+time1); double time2 = getLinkedListAndArray(loopQueue,count); System.out.println("loopQueue time2==="+time2); }
- 测试结果:
linkedListQueue time1===0.0274841 loopQueue time2===0.0528964 Process finished with exit code 0
诸葛