Java作业之容器篇

第一天

1.设计一个动态数组

 import java.util.Arrays;
public class MyArr {
    private int[] data;
    //表示当前数组中已经存储的元素个数
    private int size;

    //通过构造方法,传入一个长度为length的整形数组
    //data数组初始化,产生一个新的数组对象
    public MyArr(int length) {
        this.data = new int[length];
    }

    //在数组末尾添加一个值为val的元素
    public void add(int val) {
        data[size]= val;
        size ++;
        //判断数组是否已满,是否需要扩容
        if (size == data.length){
            grow();
        }
    }
    //在数组的index索引位置添加一个值为val的元素
    public void add(int index ,int val) {
        //首先要判断索引位置是否合法
        if (index < 0 || index > size) {
            //错误输出
            System.err.println("索引非法,请重新输入");
        }
        int ret = data[index];
        for (int i = size - 1; i >= index; i--) {
            data[i + 1] = data[i];
        }
        data[index] = val;
        size++;
        if (size == data.length) {
            grow();
        }
    }
    //查询  查询当前动态数组中第一个值为val的元素索引
    public int getByValue(int val){
        for (int i = 0; i < size; i++) {
            if (data[i] == val){
                return i;
            }
        }
        //循环走完,还未找到val,说明数组中不存在
        return -1;
    }
    //查询 查询当前动态数组中是否包含值为val的元素
    public boolean contains(int val){
        return getByValue(val) != -1;

    }

    //查询当前动态数组中索引为index的元素值
    public int get(int index){
        if(index < 0 || index >= size){
            System.err.println("索引非法,请重新输入");
            return -1;
        }
        return data[index];
    }

    //修改 修改index位置的元素为新的值newval,返回修改前的值
    public int set(int index, int newval) {
        if(index < 0 || index >= size){
            System.err.println("索引非法,请重新输入");
            return -1;
        }
        int ret = data[index];
        data[index] = newval;
        return ret;
    }

    //修改 修改第一个值oldVal 的值,更改为新的值 newVal ,返回是否修改成功
    public boolean setVal(int oldVal, int newVal){
        //利用写好的getByValue方法,判断oldVal是否存在
        int index = getByValue(oldVal);
        if (index != -1){
            data[index] = newVal;
            return true;
        }
        return false;
    }

    //删除  删除索引为index 对应的元素, 返回删除前的元素
    public int remove (int index){
        if(index < 0 ||index >= size){
            System.err.println("索引非法,请重新输入");
            return -1;
        }
        int ret = data[index];
        for (int i = index; i < size-1 ; i++) {
            data[i] = data[i+1];
        }
        size--;
        return ret ;
    }

    //删除  删除数组的头元素
    public int removeFirst(){
        return remove(0);
    }

    //删除 删除数组的尾元素
    public int removeLast(){
        return remove(size-1);
    }

    //删除  删除第一个值为val的元素,返回是否删除成功
    public boolean removeByValOnce(int val) {
        for (int i = 0; i < size; i++) {
            if (data[i] == val){
                remove(i);
                return true;
            }

        }
        return false;
    }

    //删除  删除数组中所有值为val的元素
    public void removeAllVal(int val){
        for (int i = 0; i < size; i++) {
            //内层循环也要保证索引的合法性
            while (i < size && data[i] == val){
                remove(i);
            }

        }

    }

    //扩容方法是私有的,因为对程序的使用者来说,根本不知道MyArr类中有一个数组
    //数组的扩容方法对外部也是不可见的
    private void grow() {
        this.data = Arrays.copyOf(data,data.length*2);
    }

    public String toString(){
        String ret = "[";
        for (int i = 0; i < size; i++) {
            ret += data[i];
            if(i != size-1){
                ret += ", ";
            }
        }
        ret += "]";
        return ret;
    }
}

测试

public class TestMyArr {
    public static void main(String[] args) {
        MyArr arr=new MyArr(3);
        System.out.println("扩容前数组长度为:"+arr.data.length);
        arr.add(1);
        arr.add(2);
        arr.add(2);
        arr.add(3);//添加元素
        System.out.println(arr);
        arr.remove(0);//根据下标删除
        System.out.println(arr);
        arr.removeAllVal(2);//删除所有为2的数
        System.out.println(arr);
        System.out.println("扩容后数组长度为:"+arr.data.length);
    }
}

结果为:

扩容前数组长度为:3
[1, 2, 2, 3]
[2, 2, 3]
[3]
扩容后数组长度为:6

2.设计一个栈

package Howe;

import java.util.Arrays;
public class Stack {

    private Object[] data;
    private int size;
    private int capacity;

    public Stack() {
        // 默认创建一个10容量的栈
        this.capacity = 10;
        data = new Object[this.capacity];
    }

    public Stack(int capacity) {
        this.capacity = capacity;
        data = new Object[this.capacity];
    }

    //进栈一个元素
    public void push(Object e){
        // 先判断栈是否已经满了
        if (this.isFull()) {
            // 扩容
            // 扩容的规则是原有容量的1.5倍
            int length = this.capacity + (this.capacity >>> 1);
            this.resize(length);
        } else {
            this.data[size++] = e;
        }
    }

    // 判断是否存满
    private boolean isFull() {
        return this.capacity == this.size;
    }

    // 扩容或缩容容器的大小
    private void resize(int len){
        this.data = Arrays.copyOf(this.data, len);
        this.capacity = len;
    }

    // 判断栈是否为空
    public boolean isEmpty(){
        return this.size == 0;
    }

    // 出栈一个元素
    public Object pop(){
        if (this.isEmpty()) {
            throw new RuntimeException("对不起,栈中已经没有元素了");
        }
        return this.data[--this.size];
    }

    // 查看栈顶元素
    public Object peek(){
        return this.data[this.size - 1];
    }

    // 获取栈中元素的个数
    public int size(){
        return this.size;
    }

    // 清空栈
    public void clear(){
        this.size = 0;
    }

    // 返回栈的字符串形式
    public String toString(){
        return Arrays.toString(Arrays.copyOf(this.data, this.size));
    }

    // 对比两个栈是否相等
    @Override
    public boolean equals(Object o)	{
        Stack s = (Stack) o;
        if (this.size != s.size()) {
            return false;
        }
        for (int i = 0; i < s.size() ; i++) {
            if (data[i] != s.data[i]) {
                return false;
            }
        }
        return true;
    }
}

测试类

package Howe;

public class TestStack {
    public static void main(String[] args) {
        Stack stack = new Stack();
        System.out.println(stack.isEmpty());
        stack.push("王");//添加
        stack.push("帅");//添加
        stack.push("哥");//添加
        System.out.println(stack);
        System.out.println("现有元素为:"+stack.size());//现有元素
        System.out.println(stack.isEmpty());//看是否存满
        System.out.println("栈顶元素为:"+stack.peek());//查看栈顶元素
    }
}

结果为:

true
[王, 帅, 哥]
现有元素为:3
false
栈顶元素为:哥

3.设计一个队列

package Howe;

public class Queue {

    private Stack stackA;
    private Stack stackB;

    //创建默认的队列对象
    public Queue(){
        this.stackA = new Stack();
        this.stackB = new Stack();
    }
    //进队一个元素
    public void offer(int e){
        this.stackA.push(e);
    }
    //出队一个元素
    public int poll(){
        remove();
        return (int) stackB.pop();
    }

    private void remove() {
        if (this.stackB.size() == 0){
            while (this.stackA.size() != 0){
                this.stackB.push(this.stackA.pop());
            }
        }
    }
    //查看队首元素
    public int element(){
        remove();
        return (int) this.stackB.peek();
    }
    //获取队列中元素的个数
    public int size(){
        remove();
        return this.stackB.size();
    }
    //判断队列是否为空
    public boolean isEmpty(){
        remove();
        return  this.stackB.size() == 0 && this.stackA.size() == 0;
    }
    //清空队列
    public void clear(){
        this.stackA.clear();
        this.stackB.clear();
    }
    //返回队列的字符串形式
    public String toString(){
        return this.stackB.toString();
    }
    //对比两个队列是否相等
    @Override
    public boolean equals(Object o) {
        Queue queue = (Queue) o;
        if (this.size() != queue.size()) {
            return false;
        }
        if (this.stackA.equals(queue.stackA) && this.stackB.equals(queue.stackB)){
            return true;
        }else {
            return false;
        }
    }
}

测试:

package Howe;

public class QueueTest {
    public static void main(String[] args) {
                Queue queue = new Queue();
                System.out.println("队列是否为空:"+queue.isEmpty());
                queue.offer(1);
                queue.offer(2);
                queue.offer(3);
                System.out.println("出队的元素为:"+queue.poll());
                System.out.println("队首元素为:"+queue.element());
                System.out.println("返回字符串形式为:"+queue.toString());
                Queue queue1 = new Queue();
                queue1.offer(456);
                queue1.offer(789);
                System.out.println(queue.equals(queue1));
            }
        }

结果为:

队列是否为空:true
出队的元素为:1
队首元素为:2
返回字符串形式为:[3, 2]
false

4.设计一个双向链表

public class LinkedList {
    private Node first;
    private Node last;
    private int size;

    public LinkedList() {
    }

    public void add(Object obj) {
        // 向尾部添加一个新的节点
        Node newNode = new Node();
        newNode.value = obj;
        // 判断是否是第一次添加
        if (first == null) {
            this.first = newNode;
            this.last = newNode;
        } else {
            newNode.prev = last;
            last.next = newNode;
            last = newNode;
        }
        this.size++;
    }

    public Object get(int index) {
        if (index >= this.size || index < 0) {
            throw new RuntimeException("对不起,不存在这个下标");
        }
        Node temp = first;
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }
        return temp.value;
    }

    class Node {
        Node prev;
        Node next;
        Object value;

        public Node() {
        }

        public Node(Node prev, Object value, Node next) {
            this.prev = prev;
            this.next = next;
            this.value = value;
        }
    }
}

测试

public class TestLinkedList {
    public static void main(String[] args) {
        LinkedList linkedList=new LinkedList();
        linkedList.add(123);
        linkedList.add(456);
        linkedList.add(789);
        System.out.println(linkedList.get(0));
        System.out.println(linkedList.get(1));
    }
}

结果为:

123
456

第二天

作业:

    某个人进入如下一个棋盘中,要求从左上角开始走,
    最后从右下角出来(要求只能前进,不能后退),
    其中,有些点标志为1,表示该点为无法通过的点,
    问题:共有多少种走法?

    0   0   0   0   1   0   0   0   

    0   0   0   0   0   0   1   0

    1   0   0   0   1   0   0   0

    0   0   0   0   0   0   0   0

    0   0   0   1   0   0   0   0

public class Howe {
    public static void main(String[] args) {
        int[][] list = {
                {0, 0, 0, 0, 1, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 1, 0},
                {1, 0, 0, 0, 1, 0, 0, 0},
                {0, 0, 0, 0, 1, 0, 0, 0},
                {0, 0, 0, 1, 0, 0, 0, 0},
        };
        System.out.println("共有" +  theOne(list) + "种走法");
    }

    public static int theOne(int[][] arr) {
        if (arr[0][0]==1) return 0;
        int m = arr.length, n = arr[0].length;
        int[][] dw = new int[m][n];
        for (int i = 0; i < m && arr[i][0] == 0; i++){
            dw[i][0] = 1;
        }
        for (int i = 0; i < n && arr[0][i] == 0; i++){
            dw[0][i] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (arr[i][j] == 0){
                    dw[i][j] = dw[i - 1][j] + dw[i][j - 1];
                }
            }
        }
        return dw[m - 1][n - 1];
    }
}

结果为:

一共有24种走法

容器入门篇:
        自定义容器

Java的容器主要分为2个大类,即Collection和Map。Collection代表着集合,类似数组,只保存一个数字。而Map则是映射,保留键值对两个值。

List(对付顺序的好帮手): 存储的元素是有序的、可重复的。
Set (注重独一无二的性质):存储的元素是无序的、不可重复的。
Queue (实现排队功能的叫号机):按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。
Map (用 key 来搜索的专家) :使用键值对(key-value)存储,类似于数学上的函数 y=f(x),“x” 代表 key,“y” 代表 value,key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。

java集合

集合的继承关系
    |-- Collection
        |-- List        // 线性表
        |-- Set            // 哈希表
        |-- Queue        // 队|-- Map            // 键值对,映射


注意:容器中,不能保存基本数据类型!!!
    如果一定要使用基本数据类型,则需要使用它们的包装类

注意:删除基本数据类型,需要手动装箱
    否则,int默认是下标,而不是数据本书

ArrayList源码解析:
    1、Vector默认的容量是10;
    2、Vector是线程安全的容器,操作方法都加了同步锁
    3、ArrayList是非线程安全的容器

    4、ArrayList根据调用不同的构造函数,初始化容器不同
        如果使用无参的构造,默认容量是0,节约内存,
            一旦添加元素,会发生第一次扩容,默认容量为10;

        如果有参的构造,则传递为多少,默认就是多少。

    ArrayList alist = new ArrayList();    // 默认容量0
    ArrayList alist = new ArrayList(8);    // 默认容量8

注意:  如果在开发过程中,数据大小基本确定,建议使用有参的构造函数,减少频繁扩容,提高性能当然如果不能确定的话,可以使用无参的构造。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南孚程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值