【Algorithm Part 1·Princeton】week2-1 栈、队列与背包、泛型Genetics、迭代器(接口Iterable<T>和Iterator<E>)

B站视频🔗

不论是用链表实现还是用数组实现,栈只需要1个指针。
不论是链表实现还是用数组实现,队列需要2个指针。

Stack 栈

栈的操作

用链表实现栈 ✅

用链表实现的栈,添加和删除一个结点都是在队列头完成的,即:队列头为栈顶,队列尾为栈底。

内部类Node

Node作为一个内部私有类被包含在栈的实现中

public class LinkedStackOfStrings
{
    private Node first = null;  // 首结点
    
    private class Node  // 内部类,一个Node对象即为一个结点
    {
        String item;
        Node next;
    }
    
    public boolean isEmpty()
    { return first == null; }
    
    public void push(String item)
    { /* code is below */ }
    
    public String pop()
    { /* code is below */ }
Pop操作实现
public String pop()
{
    String item = first.item;
    first = first.next;
    return item;
}

栈的内部类Node实现

Push操作实现
public void push(string item) {
    Node oldfirst = first;
    first = new Node();
    first.item = item;
    first.next = oldfirst;
}

在这里插入图片描述

链表实现栈的性质:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHjLd4gc-1644849748141)(evernotecid://E150563C-6EFF-4639-B50D-066231D9D2AE/appyinxiangcom/13134528/ENResource/p31531)]

用数组实现栈

容量N:指向数组中第一个空元素null
在这里插入图片描述

drawback
  1. 因为必须事先声明数组的长度,则用数组实现的栈的容量在被创建时就被确定了,如果栈的元素数量大于栈的容量会发生溢出,这个问题需要解决
  2. 还要考虑Java中会出现的对象游离(loitering),即在栈的数组中有对象的引用,而我们并未真正使用它,如果不做操作修正,Java的垃圾回收器不会启动【下图附解决方法,把数组中要被去除的元素对应的项设置为null,这样就不会剩下旧元素的引用,因为不存在引用了,垃圾回收器就能回收这部分内存】
    在这里插入图片描述
对drawback 1的解决
方案1:每次数组的大小只添加/减少1(not prefer,因为可能会出现抖动)

抖动:一次添加一个元素,旧数组大小为N-1,旧数组元素要被全部复制到新数组中(N-1次访问),再把新元素复制到新数组队尾(1次访问)。
所以对前N次元素的添加,复杂度为 1+2+3=…+N ~ N^2/2
在这里插入图片描述

方案2:数组满时,数组大小double;数组pop到1/4时,数组大小减半

能有效防止方案1中的抖动情况
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu5NIzsh-1644849748154)(evernotecid://E150563C-6EFF-4639-B50D-066231D9D2AE/appyinxiangcom/13134528/ENResource/p31533)]

Queue 队列

头 first/head:元素进入队列的位置
尾 last/tail: 元素出队列的位置

用链表实现

data structure

  • 一个指向队头的first指针
  • 一个指向队尾的last指针
    在这里插入图片描述
    在这里插入图片描述

implementation

  • dequeue:take from the beginning 删除队头的元素(边界:删到没有元素,null赋值给last)
  • enqueue:add to the end 在队尾添加元素(边界:链表添加前为空,last赋值给first)

用数组实现

。。。

背包 ✅

= 没有pop操作的栈 / 没有dequeue操作的队列

Genetics 泛型 ✅已写完笔记

在创建一个有泛型的类时,是无法直接创建一个Item[]数组的,而必须先声明一个Object[]数组,然后强制类型转换成Item[](lecturer说强制类型转换是ugly的,在其他代码编写中要尽量避免),这样会不可避免有一个warning,但这是Java语言本身的问题,这不可避免
❌错误的写法⬇️
在这里插入图片描述

✅正确的写法⬇️
在这里插入图片描述

不可避免的warning⬇️
在这里插入图片描述

Autoboxing

不能用基础类型作为泛型,必须使用其对应的封装类wrapper object type作为参数传进泛型

基础类型 Primitive Type封装类 Wrapper Object Type
booleanBoolean
byteByte
charCharacter
shortShort
intInteger
longLong
floatFloat
doubleDouble

在这里插入图片描述
在这里插入图片描述

Autoboxing. Automatica cast between a primitive type and its wrapper.
autoboxing:自动地在基础类型和封装类型进行互相转换。
在这里插入图片描述

interface Iterable “has a” Iterator

⬇️from ADVANCED JAVA.pdf
在这里插入图片描述

Stack<String> stack = new Stack<>();
...
for (String s : stack) {
    ...
}

↕️等于

Stack<String> stack = new Stack<>();
...
Iterator<String> iterator = stack.iterator();
while (iterator.hasNext() {
    String s = iterator.next();
    ...
}
  1. interface Iterable需要实现方法Iterator iterator()和一个实现借口interface Iterator的内部类。
    ⬇️
  2. Iterator需要实现的变量和方法:
  • private Node current;
  • public boolean hasNext() // 判断是否还有下一个节点
  • public Item next() // 将current(当前节点)移动到下一个节点
  • (public void remove() // optional(本课程不实现))

在这里插入图片描述
在这里插入图片描述

import java.util.Iterator;
public class Stack<Item> implements Iterable<Item>
{
    ...
    public Iterator<Item> iterator() { return new ListIterator(); }
    
    private class ListIterator implements Iterator<Item>
    {
        private Node current = first;
        public boolean hasNext() { return current != null; }
        public Item next()
        {
            Item item = current.item;
            current = current.next;
            return item;
        }
        public void remove() { /* optional, not supported */ }
    }
}
Modifier and TypeMethod and Description
Iteratoriterator() : Returns an iterator over elements of type T.

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值