【个人向】线性表复习

这篇文章主要是让我回忆一下以前写的线性表代码,看看其各功能(CURD等)是怎么实现的。

如果你可以完全看懂并且理解代码,那么基本的线性表应该也没什么问题,可以去做一些经典的题目来巩固和完善自己这方面的知识。

线性表大体可以分为:顺序表,链表,有序表

顺序表:使用动态数组完成的线性表,进行CURD的功能 下面代码是个简单实现的顺序表

import java.util.Arrays;

public class MyArray {
    //存储的元素仍在数组中
    private int[] data;
    // 存储中实际元素的个数.
    private int size;

    public MyArray(){
        data = new int[10];
    }
    public MyArray(int capacity){
        data = new int[capacity];
    }

    /**
     * 添加
     * @param index 要添加的数的位置
     * @param value 要添加的数值
     */
    public void addIndex(int index,int value) {
        if (size == data.length) {
            grow();
        }
        if (index < 0 || index > size) {
            System.out.println("输入的数字不合法");
            return;
        }
        for (int i = size - 1; i > index; i--) {
            data[i + 1] = data[i];
        }
        data[index] = value;
        size++;
    }


    /**
     * 删除
     * @param index 需要删除的数的位置
     */
    public void removeIndex(int index){
        if(index<0 || index >= size){
            System.out.println("输入的数字不合法");
            return;
        }
        for (int i = index; i <size - 1 ; i++) {
            data[i] = data[i+1];
        }
        size--;
        data[size] = 0;
    }

    /**
     * 删除存在的所有的value
     * @param value 需要删除的数
     */
    public void removeAllValue(int value){
        for (int i = 0; i < size; i++) {
            while(data[i] == value && i != size){
                removeIndex(i);
            }
        }
    }

    /**
     * 数组扩充
     */
    private void grow() {
        int[] newData = Arrays.copyOf(this.data,this.data.length << 1);
        this.data = newData;
    }
    /**
     * 在数组中查找value值对应的索引下标
     * @param value
     * @return
     */
    public int getByValue(int value) {
        // 遍历数组
        for (int i = 0; i < size; i++) {
            if (data[i] == value) {
                return i;
            }
        }
        // 此时循环走完还没找到元素,value不存在
        return -1;
    }
    /**
     * 根据索引查询元素
     * @param index 索引值
     * @return
     */
    public int get(int index) {
        // 判断合法性
        if (index < 0 || index >= size) {
            System.out.println("get index illegal!");
            return -1;
        }
        return data[index];
    }
    /**
     * 将指定索引位置元素修改为newValue,返回修改前的元素值
     * @param index
     * @param newValue
     * @return
     */
    public int set(int index,int newValue) {
        // 判断合法
        if (index < 0 || index >= size) {
            System.out.println("set index illegal!");
            return -1;
        }
        int oldValue = data[index];
        data[index] = newValue;
        return oldValue;
    }

    /**
     * 打印
     * @return 返回值
     */
    public String toString(){
        String ret = "[";
        for (int i = 0; i < size; i++) {
            ret += data[i];
            if(i != size - 1){
                ret += ",";
            }
        }
        ret += "]";
        return ret;
    }
}

链表:所谓链表可以想成火车 ,车厢里装载着值(val),通过相连车厢(prev,next)可以实现出一个顺序表结构。下面代码类比火车,方便理解。

public class SingleLinkedList {
    // 当前火车中车厢的节点个数(实际就是具体元素的个数)
    private int size;
    // 当前火车的火车头
    private Node head;

    /**
     * 在火车头部添加元素-添加一个车厢节点
     * @param val
     */
    public void addFirst(int val) {
        // 新建一个车厢节点
        Node node = new Node(val);
        // 判断当前的火车是否为空
        if (head == null) {
            head = node;
        }else {
            // 火车中有节点,要把当前新车厢挂载到火车头部
            node.next = head;
            head = node;
        }
        size ++;
    }

    /**
     * 在单链表的任意一个索引位置插入元素val
     * @param index
     * @param val
     */
    public void addIndex(int index,int val) {
        // 1.合法性
        if (index < 0 || index > size) {
            System.err.println("add index illegal!");
            return;
        }
        // 头插法
        if (index == 0) {
            addFirst(val);
            return;
        }
        // 2.插入元素
        Node node = new Node(val);
        // 需要找到待插入位置的前驱,从头节点开始向后依次走index - 1步
        Node prev = head;
        for (int i = 0; i < index - 1; i++) {
            prev = prev.next;
        }
        // 此时prev指向待插入位置的前驱节点
        node.next = prev.next;
        prev.next = node;
        size ++;
    }
    // 在单链表的尾部插入元素
    public void addLast(int val) {
        addIndex(size,val);
    }

    /**
     * 根据用户输入的index查找对应值
     * @param index
     * @return
     */
    public int get(int index) {
        if(rangeCheck(index)) {
            // index合法
            // 从头节点开始遍历链表,走到index位置
            Node node = head;
            // 规定了node节点走的步数
            for (int i = 0; i < index; i++) {
                node = node.next;
            }
            return node.val;
        }else {
            System.err.println("get index illegal!");
            return -1;
        }
    }

    /**
     * 判断当前链表中是否包含值为val的节点
     * @param val
     * @return
     */
    public boolean contains(int val) {
        for (Node temp = head;temp != null;temp = temp.next) {
            if (temp.val == val) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将单链表中索引为index的节点值改为newVal
     * @param index
     * @param newVal
     * @return 修改前的值
     */
    public int set(int index,int newVal) {
        if (rangeCheck(index)) {
            Node node = head;
            for (int i = 0; i < index; i++) {
                node = node.next;
            }
            int oldVal = node.val;
            node.val = newVal;
            return oldVal;
        }else {
            System.err.println("set index illegal!");
            return -1;
        }
    }

    public void removeIndex(int index) {
        // 1.判断合法性
        if (rangeCheck(index)) {
            // 2.边界 删除头节点的情况
            if (index == 0) {
                // 删除头节点
                Node temp = head;
                head = head.next;
                temp.next = null;
                size --;
            }else {
                // index中间位置
                // 找到待删除节点的前驱
                Node prev = head;
                for (int i = 0; i < index - 1; i++) {
                    prev = prev.next;
                }
                // 待删除节点
                Node cur = prev.next;
                prev.next = cur.next;
                cur.next = null;
                size --;
            }
        }else {
            System.err.println("remove index illegal!");
        }
    }

    public void removeFirst() {
        removeIndex(0);
    }

    public void removeLast() {
        removeIndex(size - 1);
    }

    public void removeValueOnce(int val) {
        // 遍历链表,找到值为val的节点 -> 不知道值为val的节点在哪个位置
        // 找到后删除(正常的删除都需要找到前驱,只有头节点没前驱)
        if (head != null && head.val == val) {
            // 头节点就是待删除的节点
            Node temp = head;
            head = head.next;
            temp.next = null;
            size --;
        }else {
            // 此时head一定不是待删除的节点
            Node prev = head;
            // 判断前驱的下一个节点值是否等于val
            // 看你取值用的是哪个引用,就判断哪个引用不为空
            while (prev.next != null) {
                // cur就是待删除的节点
                if (prev.next.val == val) {
                    Node cur = prev.next;
                    // 删除cur
                    prev.next = cur.next;
                    cur.next = null;
                    size --;
                    return;
                }
                // prev不是待删除节点的前驱,prev向后移动
                prev = prev.next;
            }
        }
    }

    public void removeValueAll(int val) {
        // 判断头节点是否是待删除节点
        while (head != null && head.val == val) {
            head = head.next;
            size --;
        }
        if (head == null) {
            // 此时链表中的值全是val
            return;
        }else {
            Node prev = head;
            while (prev.next != null) {
                if (prev.next.val == val) {
                    Node cur = prev.next;
                    // 删除cur
                    prev.next = cur.next;
                    cur.next = null;
                    size --;
                }else {
                    prev = prev.next;
                }
            }
        }
    }

    /**
     * 判断用户输入的index是否合法(改,查,删除使用)
     * @param index
     * @return
     */
    private boolean rangeCheck(int index) {
        if (index < 0 || index >= size) {
            return false;
        }
        return true;
    }


    public String toString() {
        String ret = "";
        // 遍历火车这个类,
        // 从火车头(head)走到火车尾部
        // 暂时存储当前头节点地址
        Node node = head;
        while (node != null) {
            ret += node.val;
            ret += "->";
            // 继续访问下一节车厢
            node = node.next;
        }
        ret += "NULL";
        return ret;
    }
}
/**
 * 火车车厢类,一个车厢只能保存一个元素
 */
class Node {
    // 存储具体数据
    int val;
    // 保存下一个车厢的地址
    Node next;
    public Node(int val) {
        this.val = val;
    }
}

最后一段的火车车厢类,其实就是节点类Node。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值