剑指offer——双向链表

        相比较于单链表来说,双向链表比之也相差不远,在单链表的文章说说过,节点之间有一个钩子属性存在,相比较于单链表,双向链表的钩子属性多了一个,多了一个前钩子属性。

        双链表的初始化比之单链表多了一个前钩子属性,代码如下:
 

class HodeNodeDouble {
    private int id;
    private String name;
    //前钩子
    public HodeNodeDouble pre;
    //后钩子
    public HodeNodeDouble next;

    public HodeNodeDouble(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "HodeNodeDouble{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

        在添加数据的方法中,从单链表的

temp.next = hodeNode;

        变成了

temp.next = hodeNodeDouble;
hodeNodeDouble.pre = temp;

        具体的代码如下:

    //增加节点
    public void add(HodeNodeDouble hodeNodeDouble) {
        if (head.next == null) {
            head.next = hodeNodeDouble;
            hodeNodeDouble.pre = head;
            return;
        }
        HodeNodeDouble temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = hodeNodeDouble;
        hodeNodeDouble.pre = temp;
    }

        删除节点的方法变化大了一点点,辅助节点temp不是从head开始了,而是从head.next开始了,当然,也可以从head开始,但是后面的代码编写看起来可能会很奇怪,不利于我们去get到里面的逻辑,会有点绕,所以就改成了head.next,然后删除的逻辑代码也从单链表的

temp.next = temp.next.next;

         变成了

temp.pre.next = temp.next;
if (temp.next != null){
    temp.next.pre = temp.pre;
}

        具体的代码实现如下:

    //删除节点
    public void pop(HodeNodeDouble hodeNodeDouble) {
        if (head.next == null) {
            return;
        }
        HodeNodeDouble temp = head.next;
        while (true) {
            if (temp == null) {
                System.out.println("没有找到id为" + hodeNodeDouble.getId() + "的节点");
                break;
            }
            if (temp.getId() == hodeNodeDouble.getId()) {
                temp.pre.next = temp.next;
                if (temp.next != null){
                    temp.next.pre = temp.pre;
                }
                break;
            }
            temp = temp.next;
        }
    }

        其他的方法双向链表与单链表的相差也不大,就不过多的解释说明了,直接上代码了。

/**
 * 双向链表
 */
public class DoubleLinkedListDemo {
    public static void main(String[] args) {
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();

        HodeNodeDouble hodeNode1 = new HodeNodeDouble(1, "qqq");
        HodeNodeDouble hodeNode2 = new HodeNodeDouble(2, "www");
        HodeNodeDouble hodeNode3 = new HodeNodeDouble(3, "ttt");
        HodeNodeDouble hodeNode4 = new HodeNodeDouble(4, "eee");
        HodeNodeDouble hodeNode5 = new HodeNodeDouble(5, "rrr");
        HodeNodeDouble hodeNode6 = new HodeNodeDouble(6, "yyy");

        doubleLinkedList.add(hodeNode1);
        doubleLinkedList.add(hodeNode2);
        doubleLinkedList.add(hodeNode3);
        doubleLinkedList.add(hodeNode4);
        doubleLinkedList.add(hodeNode5);

        System.out.println("=======遍历========");
        doubleLinkedList.list();
        System.out.println("=======删除节点遍历========");
        doubleLinkedList.pop(hodeNode3);
        doubleLinkedList.list();
        System.out.println("=======根据id查询节点的信息========");
        System.out.println(doubleLinkedList.get(2));
        System.out.println("=======插入节点遍历========");
        doubleLinkedList.insertNode(hodeNode3);
        doubleLinkedList.insertNode(hodeNode6);
        doubleLinkedList.list();
    }
}

/**
 * 创建双向链表的常用方法
 */
class DoubleLinkedList {
    //创建头节点,方便遍历
    private HodeNodeDouble head = new HodeNodeDouble(0, "");

    //增加节点
    public void add(HodeNodeDouble hodeNodeDouble) {
        if (head.next == null) {
            head.next = hodeNodeDouble;
            hodeNodeDouble.pre = head;
            return;
        }
        HodeNodeDouble temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = hodeNodeDouble;
        hodeNodeDouble.pre = temp;
    }

    //获取节点
    public HodeNodeDouble get(int id) {
        if (head.next == null) {
            return null;
        }
        HodeNodeDouble temp = head;
        while (true) {
            if (temp.next == null) {
                System.out.println("没有找到id为" + id + "的节点");
                return null;
            }
            if (temp.next.getId() == id) {
                break;
            }
            temp = temp.next;
        }
        return temp.next;
    }

    //遍历链表
    public void list() {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HodeNodeDouble temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            System.out.println(temp.next);
            temp = temp.next;
        }
    }

    //删除节点
    public void pop(HodeNodeDouble hodeNodeDouble) {
        if (head.next == null) {
            return;
        }
        HodeNodeDouble temp = head.next;
        while (true) {
            if (temp == null) {
                System.out.println("没有找到id为" + hodeNodeDouble.getId() + "的节点");
                break;
            }
            if (temp.getId() == hodeNodeDouble.getId()) {
                temp.pre.next = temp.next;
                if (temp.next != null){
                    temp.next.pre = temp.pre;
                }
                break;
            }
            temp = temp.next;
        }
    }

    //插入节点
    public void insertNode(HodeNodeDouble hodeNodeDouble) {
        if (head.next == null) {
            return;
        }
        HodeNodeDouble temp = head.next;
        while (true) {
            if (temp == null) {
                //当当前链表循环结束还是未找到对应的位置,则调用add直接添加在链表最后
                add(hodeNodeDouble);
                break;
            }
            if (temp.getId() > hodeNodeDouble.getId()) {
                temp.pre.next = hodeNodeDouble;
                hodeNodeDouble.pre = temp.pre;
                return;
            }
            temp = temp.next;
        }
    }
}

/**
 * 创建节点
 */
class HodeNodeDouble {
    private int id;
    private String name;
    //前钩子
    public HodeNodeDouble pre;
    //后钩子
    public HodeNodeDouble next;

    public HodeNodeDouble(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "HodeNodeDouble{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

        此上就是我对双向链表的所有理解和代码实现,如有不对,烦请大佬指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

super 琪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值