Java实现:双向链表实现线性表

/*
通过双向链表来实现线性表,增删改查功能(重点掌握:java的唯一值传递本质)
 */
//测试
public class MyListTest {
    public static void main(String[] args) {
        MyDBLinked myDBLinked = new MyDBLinked();
        myDBLinked.add("a");
        myDBLinked.add("b");
        myDBLinked.add("c");
        myDBLinked.add("d");
//        myDBLinked.remove("d");
//        System.out.println(myDBLinked.get(0));
//        System.out.println(myDBLinked.set(3,"zs"));
//        System.out.println(myDBLinked.contains("e"));
//        System.out.println(myDBLinked.insert(4, "zs"));
        myDBLinked.remove(3);
        System.out.println(myDBLinked);
    }
}
//双向链表类
class MyDBLinked {
    private Node head;
    private Node end;
    private int size;
    /**
     * 尾结点添加元素的方法
     * @param s:传入的节点数据
     * @return 返回添加元素是否成功
     */
    public boolean add(String s) {
        if (s == null) throw new IllegalArgumentException("param is Illegal");
        //如果链表为空,让头尾都等于新节点
        if (head == null || size == 0) {
            head = new Node(null, s, head);
            end = head;
            size++;
            return true;
        }
        //如果不为空,直接在尾节点添加元素
        Node node = new Node(null, s, null);
        node.pre = end;
        end.next = node;
        end = node;
        size++;
        return true;
    }

    /**
     *根据提供的内容删除指定元素
     * @param s:查找的value
     * @return 是否删除成功
     */
    public boolean remove(String s){
        //如果查找的值是空或者链表是空,直接抛出异常
        if(s==null) throw new IllegalArgumentException("param is null");
        if(head==null||size==0)throw new RuntimeException("Linked is null");
        //如果需要删除的元素为头结点
        if(head.value.equals(s)){
            head = head.next;
            //如果链表只有一个元素,删除唯一的头结点
            if(head == null){
                end = null;
            }else {//链表不止一个元素
                head.pre = null;
            }
            size--;
            return true;
        }
        //要删除的节点不是头节点
        Node mid = head;
        while (mid.next!=null&&!mid.next.value.equals(s)){
            mid = mid.next;
        }
        //如果找到最后一个节点还没有找到目标值元素,代表值不存在
        if(mid.next==null) return false;
        //mid 为要删除的节点的前一个节点
        Node removeNode = mid.next;
        //如果要删除的是尾结点
        if(removeNode.next==null){
            mid.next = null;
        }else {
            removeNode.pre.next = mid.next.next;
            removeNode.next.pre = mid;
        }
        size--;
        return true;
    }
    /**
     * 判断链表元素是否包含某一个值
     * @param s:要判断的value
     * @return true存在
     */
    public boolean contains(String s){
        //如果查找的值是空或者链表是空,直接抛出异常
        if(s==null) throw new IllegalArgumentException("param is null");
        if(head==null||size==0)throw new RuntimeException("Linked is null");
        if(head.value.equals(s)) return true;
        Node mid = head;
        while (mid.next!=null&&!mid.next.value.equals(s)){
            mid = mid.next;
        }
        //如果判断到了mid.next == null退出循环,代表查找数据不存在
        if(mid.next==null) return false;
        //到此处代表查找数据存在
        return true;
    }

    /**
     * 按指定下标位置插入元素
     * @param index:插入元素的下标位置  [0,size]
     * @param s:插入元素的value
     * @return 是否插入成功
     */
    public boolean insert(int index,String s){
        //如果查找的值是空或者链表是空,直接抛出异常
        if(s==null||index<0||index>size) throw new IllegalArgumentException("param is null");
        //如果插入点为头结点
        if(index==0){
            //如果链表为空
            if(size==0){
                head = new Node(null,s,null);
                end = head;
            }else {//链表不为空,size为1时head前移,end不变不用考虑
                Node node = new Node(null, s, head);
                head.pre = node;
                head = node;
            }
            size++;
            return true;
        }
        //插入的点不是头结点
        //如果从尾部插入元素
        if(index==size){
            //调用前面的方法
            return add(s);
        }
        Node mid;
        //如果下标靠近头节点,从前往后遍历
        if(index<size/2){
            int tag = 1;//如果从0开始就会找到要插入间隙的后一个节点
            mid = head;
            //当找到要插入间隙的前节点mid时退出循环
            while (index!=tag){
                mid = mid.next;
                tag++;
            }
        }else {//如果下标靠近尾节点,从后往前遍历
            int tag = size;//如果从size-1开始就会找到要插入间隙的后一个节点
            mid = end;
            while (index!=tag){
                mid = mid.next;
                tag--;
            }
        }
        //mid始终是要插入间隙的前一个节点元素
        Node node = new Node(mid, s, mid.next);
        mid.next = node;
        mid.next.pre = node;
        size++;
        return true;
    }

    /**
     * 按照指定下标删除节点
     * @param index:删除节点的下标    [0,size)
     * @return 被删除节点的value
     */
    public String remove(int index){
        if(head==null||size==0) throw new RuntimeException("Linked is null");
        if(index<0||index>=size) throw new IllegalArgumentException("param is illegal : index="+index);
        //如果删除的是头结点
        if(index == 0){
            //暂存头结点值
            String oldValue = head.value;
            //链表只有一个元素
            if(head.next==null||size == 1) {
                head = null;
                end = null;
            }else {//链表由两个或两个以上的元素
                head = head.next;
                head.pre = null;
            }
            return oldValue;
        }
        //要删除的不是头结点
        //如果要删除的节点是尾结点
        if(index==(size-1)){
            String oldValue = end.value;
            end.pre.next = null;
            end = end.pre;
            return oldValue;
        }
        Node mid = head;//mid就是要删除的节点
        if(index<size/2){//如果下标离头结点近,向后遍历
            int tag = 0;
            mid = head;
            while (index!= tag){
                mid = mid.next;
                tag++;
            }
        }else {//如果下标离尾结点近,向前遍历
            int tag = size-1;
            mid = end;
            while (index!=tag){
                mid = mid.pre;
                tag--;
            }
        }
        String oldValue = mid.value;
        mid.pre.next = mid.next;
        mid.next.pre = mid.pre;
        return oldValue;
    }
    /**
     * 根据下标查找对应节点的值
     * @param index:要查询的元素下标
     * @return 返回节点的value值
     */
    public String get(int index) {
        //如果链表为空
        if (head == null || size == 0) throw new RuntimeException("Linked is null");
        //如果下标小于0或者超过size-1
        if (index < 0 || index >= size) throw new IllegalArgumentException("param is illegal:index=" + index);
        Node mid;
        //如果查询下标靠近头结点,从头结点向后遍历
        if (index < size / 2) {
            mid = head;
            int tag = 0;
            while (index != tag) {
                mid = mid.next;
                tag++;
            }
        }else {//如果查询下标靠近尾结点,从尾结点开始向前遍历
            mid = end;
            int tag = size-1;
            while (index!=tag){
                mid = mid.pre;
                tag--;
            }
        }
        return mid.value;
    }

    /**
     * 根据下标和新的元素value替换原来的value
     * @param index:需要修改的元素的下标
     * @param newValue:需要替换的原来元素value值的新值
     * @return 返回被修改的value值
     */
    public String set(int index, String newValue) {
        //如果链表为空
        if (head == null || size == 0) throw new RuntimeException("Linked is null");
        //如果下标小于0或者超过size-1
        if (index < 0 || index >= size) throw new IllegalArgumentException("param is illegal:index=" + index);
        Node mid;
        //如果查询下标靠近头结点,从头结点向后遍历
        if (index < size / 2) {
            mid = head;
            int tag = 0;
            while (index != tag) {
                mid = mid.next;
                tag++;
            }
        }else {//如果查询下标靠近尾结点,从尾结点开始向前遍历
            mid = end;
            int tag = size-1;
            while (index!=tag){
                mid = mid.pre;
                tag--;
            }
        }
        //保存旧值并更新,返回旧值
        String oldValue = mid.value;
        mid.value = newValue;
        return oldValue;
    }
    /**
     * 求链表长度的方法
     * @return
     */
    public int size(){
        return size;
    }
    /**
     * 判断链表是否为空的方法
     * @return ture就是链表为空
     */
    public boolean isEmpty(){
        return size==0;
    }
    //节点类
    class Node {
        Node pre;
        String value;
        Node next;
        //节点构造器
        private Node(Node pre, String value, Node next) {
            this.pre = pre;
            this.value = value;
            this.next = next;
        }
        @Override
        public String toString() {
            //节点toString方法不能包含pre,不然会循环调用导致栈溢出
            return "Node{" +
                    "v='" + value +
                    ", next=" + next +
                    '}';
        }
    }
    @Override
    public String toString() {
        return "{" +
                "head=" + head +
                '}';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值