欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构与算法——双链表

程序员文章站 2024-03-16 15:39:22
...

目录

前言

一、双向链表

二、使用步骤

1.设定双向链表的基本属性

2.读取双链表的方法

3.测试双链表

4.测试结果


 


前言

1) 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。

2) 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除。

3) 分析双向链表如何完成遍历,添加,修改和删除


一、双向链表

分析双向链表的遍历,添加,修改,删除的操作思路

 1) 遍历 和单链表一样,只是可以向前,也可以向后查找

2) 添加 按照标号顺序添加

3) 修改 思路和向链表一样

4) 删除 实现自我删除某个节点 

二、使用步骤

1.设定双向链表的基本属性

class DoubleLinked {
    private int number; // 编号
    private String name;// 名称
    private DoubleLinked next;// 指向下一个数据节点
    private DoubleLinked pre;// 指向前一个节点

    public DoubleLinked(int number, String name) {// 构造器初始化基本值
        super();
        this.number = number;
        this.name = name;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public DoubleLinked getNext() {
        return next;
    }

    public void setNext(DoubleLinked next) {
        this.next = next;
    }

    public DoubleLinked getPre() {
        return pre;
    }

    public void setPre(DoubleLinked pre) {
        this.pre = pre;
    }

    public String getInfo() {// 获取信息
        return "编号:" + number + "姓名:" + name;
    }
}

2.读取双链表的方法

class DoubleLinkedListMethod {
    private DoubleLinked head = new DoubleLinked(0, "");// 定义头结点

    public void add(DoubleLinked a) {// 增加数据
        DoubleLinked temp = head;// 头结点不能动,采用临时变量
        boolean flag = false;
        // 按编号顺序添加
        while (true) {
            if (temp.getNext() == null) {// 指向的下一个数据为空,说明temp到达链表尾部
                break; // 注意:链表没有长度限制
            }
            if (temp.getNext().getNumber() > a.getNumber()) {// 如果temp指向的下一个节点编号大于要添加的编号,说明要添加的编号,在temp指向的下一个位置
                break;
            } else if (temp.getNext().getNumber() == a.getNumber()) {// 如果temp指向的下一个节点编号等于要添加的编号,说明要添加的编号已存在
                flag = true;
                break;
            }
            temp = temp.getNext();// 如果都不满足,后移一位
        }
        if (flag) {
            System.out.println("编号为:" + a.getNumber() + "的人已存在,无法添加");
        } else {
            // 将编号插入temp后面
            a.setNext(temp.getNext());// 把temp的next给添加的数据
            if (a.getNext() != null) {// 当a的下一个节点不为空
                a.getNext().setPre(a);// 把下一个节点的pre指向a,形成双向链表
            }
            temp.setNext(a);// 再把temp的next指向添加的数据
            a.setPre(temp);// 最后a的pre指向temp,形成双向链表
        }
    }

    public void replace(DoubleLinked a) {// 修改数据
        if (head.getNext() == null) {// 头结点指向的下一个数据为空
            System.out.println("链表没有数据,无法修改");
            return;// 结束replace方法
        }
        DoubleLinked temp = head;// 头结点不能动,采用临时变量
        boolean flag = false;
        while (true) {
            if (temp.getNext() == null) {// 到达链表尾部
                break;
            } else if (temp.getNext().getNumber() == a.getNumber()) {// 找到要修改的编号
                flag = true;
                break;
            }
            temp = temp.getNext();// 都不满足,temp后移一位
        }
        if (flag) {
            temp.getNext().setName(a.getName());// 修改姓名
        } else {
            System.out.println("编号有误,请重新输入");
        }
    }

    public void delete(DoubleLinked a) {// 删除数据
        if (head.getNext() == null) {// 头结点指向的下一个数据为空
            System.out.println("链表没有数据,无法删除");
            return;// 结束delete方法
        }
        DoubleLinked temp = head.getNext();// 头结点不能动,采用临时变量
                                            // 将temp定义在第一个数据
        boolean flag = false;
        while (true) {
            if (temp == null) {// 到达链表尾部
                break;
            } else if (temp.getNumber() == a.getNumber()) {// 找到要删除的编号
                flag = true;
                break;
            }
            temp = temp.getNext();// 都不满足,temp后移一位
        }
        if (flag) {// 找到时,temp指向要修改的数据
            // 修改方法:不同于单向链表,可以在自身位置处进行删除
            temp.getPre().setNext(temp.getNext());// 把temp前一个节点的next指向temp后一个节点
            if (temp.getNext() != null) {//如果temp的下一个节点不为空
                temp.getNext().setPre(temp.getPre());// 把temp后一个节点的next指向temp前一个节点
            }
        } else {
            System.out.println("编号有误,请重新输入");
        }
    }

    public void show() {// 显示列表(遍历)
        DoubleLinked temp = head;// 头结点不能动,采用临时变量
        if (temp.getNext() == null) {// 如果头结点指向的第一个数据为空,说明链表为空
            System.out.println("链表没有数据");
        } else {
            while (true) {
                if (temp.getNext() != null) {// 此时逐一遍历,下一个节点为空时停止
                    System.out.println(temp.getNext().getInfo());// 输出next指向下一个节点的信息
                } else {
                    break;
                }
                temp = temp.getNext();// 每取出一个数据,临时变量的next后移一位
            }
        }
    }
}

3.测试双链表

public class DoubleLinkedList {
    public static void main(String[] args) {
        DoubleLinkedListMethod test = new DoubleLinkedListMethod();
        DoubleLinked a = new DoubleLinked(1, "Tom");
        DoubleLinked a1 = new DoubleLinked(9, "San");
        DoubleLinked a2 = new DoubleLinked(3, "Bete");
        DoubleLinked a3 = new DoubleLinked(7, "Jerry");
        DoubleLinked a4 = new DoubleLinked(5, "Huddy");
        test.add(a1);
        test.add(a3);
        test.add(a4);
        test.add(a2);
        test.add(a);
        System.out.println("修改前");
        test.show();
        
        System.out.println("修改后");
        DoubleLinked a0 = new DoubleLinked(3, "Lily");
        test.replace(a0);
        test.show();
        
        System.out.println("删除后");
        test.delete(a);
        test.delete(a1);
        test.show();
    }

}

4.测试结果

数据结构与算法——双链表