数据结构 链表

数据结构 链表
  • 本来正常的 都要 理论一大堆 链表是一种物理存储单元上非连续、非顺序的存储结构… 巴拉巴拉 一大堆
  • 但是嘛 我偏不 直接上代码
  • 项目 用的 普通的 MAVEN Java 项目
单向链表
  • 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
package com.codervibe.ch01;

/**
 * 这只是个单链表
 *
 */

public class OneWayLinkList<T> {
    //记录头节点
    public Node head;
    // 记录链表的长度
    public int length;



    //节点类
    private class Node {
        //存储数据
        T item;
        //下一个节点
        Node next;
        public Node() {

        }

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }


    }

    public OneWayLinkList() {
        //初始化 头节点
        this.head = new Node();
        // 初始化 元素个数
        this.length = 0;

    }

    // 清空链表
    public void clear() {
        this.head = null;
        this.length = 0;
    }

    // 获取链表最大长度 (返回N即可)
    public int length() {
        return length;
    }

    // 判断链表是否为空(判断 N 是否 为 0 即可)
    public boolean isEmpty() {
        return length == 0;
    }

    //获取指定位置的元素 (用一个临时的结点指向头节点,不断让临时
    // 节点指向它的下一个结点)
    public T get(int i) {
        //通过循环,从头节点开始往后查找
        Node node = head;
        for (int j = 0; j <= i; j++) {
            node = node.next;
        }
        return node.item;
    }

    //向链表中 添加元素
    public void insert(T t) {
        //找到当前最后一个结点
        Node last = head;
        while (last.next != null) {
            last = last.next;
        }
        //创建新节点 保存元素t
        Node now = new Node(t, null);
        //让当前最后一个结点指向新的结点
        last.next = now;
        //然后让元素个数加一
        this.length++;
    }

    //向链表中的指定位置 添加元素
    public void insert(int i, T t) {
        Node pre = head;
        //找到i位置的前一个结点
        for (int j = 0; j < i; j++) {
            pre = pre.next;

        }
        //找到位置的结点
        Node cur = pre.next;
        //创建新结点 前一结点 指向新节点 新节点只想原来i 位置的结点
        Node now = new Node(t, cur);
        pre.next = now;
        //元素个数加一
        this.length++;
    }
    //删除指定位置元素
    public  T remove(int i) {
        //找到i位置前一个结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            head = pre.next;
        }
        //找到i 位置的节点并保存
        Node cur = pre.next;
        //找到 i 位置下一个节点
        Node next = cur.next;
        //前一个结点指向下一个结点
        pre.next =next;
        // 元素个数减一
        this.length--;
        return cur.item;
    }
    public int indexOf(T t){
        // 从头开始依次查找每一个节点,取出 item 和 t 比较,如果相同 则找到了
        Node now =head;
        for (int i = 0; now.next != null; i++) {
            now =now.next;
            if (now.item == t) {
                return i;
            }

        }
        //找不到就返回 -1;
        return - 1;
    }
}
  • 对 上述的代码进行测试
    @Test // 注解 就是 junit 的 测试注解 
    public void OneWayLinkListTest() {
        OneWayLinkList<String> oneWayLinkList =new OneWayLinkList<>();
        oneWayLinkList.insert("孙悟空");
        oneWayLinkList.insert("猪八戒");
        oneWayLinkList.insert("貂蝉");
        oneWayLinkList.insert("吕布");
        oneWayLinkList.insert("老夫子");
        oneWayLinkList.insert("盘古");
        oneWayLinkList.insert("后羿");
        oneWayLinkList.insert("扁鹊");

        for (int i = 0; i < oneWayLinkList.length(); i++) {
            System.out.println(oneWayLinkList.get(i));
        }
        System.out.println("当前的链表长度为:" + oneWayLinkList.length());
        System.out.println("-------------------------------------");
        //测试获取
        String getLinkList = oneWayLinkList.get(5);
        System.out.println("获取索引的位置的结果为:"+getLinkList);
        //测试删除
        String removeItem= oneWayLinkList.remove(4);
        System.out.println("删除的元素为 " + removeItem+"\t"+"删除后的长度为"+ oneWayLinkList.length());
        //测试返回元素第一次出现的索引
        System.out.println("扁鹊 第一次出现的索引为 " + oneWayLinkList.indexOf("扁鹊"));
        //测试清空
        oneWayLinkList.clear();
        System.out.println("清空后链表中元素的个数为"+ oneWayLinkList.length());
    }
双向链表
package com.codervibe.ch01;

public class TwoWayLinkList<T> {
    private Node head;
    private Node last;
    private int length;

    private class Node {
        public T item;
        //指向前一个结点
        public Node pre;
        //指向后一个结点
        public Node next;

        public Node(T item, Node pre, Node next) {
            this.item = item;
            this.pre = pre;
            this.next = next;
        }

    }

    //初始化头结点 尾结点指向null 初始链表长度为0
    public TwoWayLinkList() {
        //初始化 头节点和 尾结点
        this.head = new Node(null, null, null);
        this.last = null;
        //初始化元素的个数
        this.length = 0;
    }

    //清空链表(头节点,尾结点置空,链表长度置为零)
    public void clear() {
        this.head.next = null;
        this.last = null;
        this.length = 0;
    }

    //获取链表的长度
    public int length() {
        return this.length;
    }

    //判断链表是否为空
    public boolean isEmpty() {
        return length == 0;
    }

    //获取第一个元素
    public T getFileItem() {
        if (isEmpty()) {
            return null;
        }
        return head.next.item;
    }

    //获取第二个元素
    public T getLastItem() {
        if (isEmpty()) {
            return null;
        }
        return last.item;
    }

    public void insert(T t) {
        //如果链表为空
        if (isEmpty()) {
            //创建新节点,pre指向头节点
            Node newNode = new Node(t, head, null);
            // 让新节点 成为 尾结点
            last = newNode;
            //让头节点成为尾结点
            head.next = last;
        } else {
            // 如果不为空
            //创建新的结点
            Node newNode = new Node(t, last, null);
            //让当前尾结点指向新的结点
            last.next = newNode;
            //让新节点成为尾结点
            last = newNode;
        }
        //元素个数加一
        this.length++;
    }

    public void insert(int i, T t) {
        //找到i 位置的前一个结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            pre = pre.next;
        }
        //找到 i 的位置的结点
        Node cur = pre.next;
        //创建新节点,让其pre指向前一个结点,next 指向 i 位置结点
        Node newNode = new Node(t, pre, cur);
        //将前一个结点的next 变为新节点
        pre.next = newNode;
        // 让 i 位置的 pre 变为 新节点
        cur.pre = newNode;
        //元素个数 加一
        this.length++;

    }

    // 获取指定位置 元素
    public T getItem(int i) {
        //通过循环,从头节点 开始往后查找
        Node node = head;
        for (int j = 0; j < i; j++) {
            node = node.next;
        }
        return node.item;
    }
    // 获取指定元素的第一次出现的索引
    public int indexOf(T t) {
        //从头开始依次查找每一个结点,
        // 取出item 和 他比较,如果相同 则找到了 否则返回 -1

        Node now = head;
        for (int i = 0; now.next != null; i++) {
            now = now.next;
            if (now.item == t) {
                return i;
            }

        }
        //  找到不到就返回 -1
        return -1;
    }
    //删除指定元素并返回
    public T remove(int i){
        //找到前一个 结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            pre =pre.next;
        }
        //找到 i 位置的下一个结点
        Node cur = pre.next;
        //找到下一个结点
        Node nextNode = cur.next;
        //让前一个结点的next 指向下一个结点
        pre.next = nextNode;
        // 让下一个结点的pre 指向前一个结点
        nextNode.pre = pre;
        //元素个数减一
        this.length--;
        return cur.item;
    }

}
  • 对上述代码进行测试
@Test
    public void TwoWayLinkListTest(){
        TwoWayLinkList<String> twoWayLinkList=new TwoWayLinkList<>();
        twoWayLinkList.insert("孙悟空");
        twoWayLinkList.insert("猪八戒");
        twoWayLinkList.insert("貂蝉");
        twoWayLinkList.insert("吕布");
        twoWayLinkList.insert("老夫子");
        twoWayLinkList.insert("盘古");
        twoWayLinkList.insert("后羿");
        twoWayLinkList.insert("扁鹊");
        for (int i = 0; i < twoWayLinkList.length(); i++) {
            System.out.println(twoWayLinkList.getItem(i));
        }
        System.out.println("当前列表的长度为:" + twoWayLinkList.length());
        System.out.println("----------------------------------------------------------");
        //测试获取
        System.out.println("获取索引位置的元素为" + twoWayLinkList.getItem(6));
        //测试删除
        System.out.println("删除的元素为  " + twoWayLinkList.remove(4)+ "删除后的 链表长度为:"+twoWayLinkList.length());
        //测试返回元素第一次出现的索引
        System.out.println("吕布 出现的 第一次索引为 " + twoWayLinkList.indexOf("吕布"));
        //测试在 指定索引的位置插入
        twoWayLinkList.insert(4,"李元芳");
        System.out.println("插入新元素之后 链表为");
        for (int i = 0; i < twoWayLinkList.length(); i++) {
            System.out.println(twoWayLinkList.getItem(i));
        }
        //测试清空链表 方法
        System.out.println("清空链表~~~");
        twoWayLinkList.clear();
        System.out.println("链表清空后的 的链表长度为 :" + twoWayLinkList.length());
    }
两个类的 全部代码
  • 单链表
package com.codervibe.ch01;

/**
 * 这只是个单链表
 *
 */

public class OneWayLinkList<T> {
    //记录头节点
    public Node head;
    // 记录链表的长度
    public int length;



    //节点类
    private class Node {
        //存储数据
        T item;
        //下一个节点
        Node next;
        public Node() {

        }

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }


    }

    public OneWayLinkList() {
        //初始化 头节点
        this.head = new Node();
        // 初始化 元素个数
        this.length = 0;

    }

    // 清空链表
    public void clear() {
        this.head = null;
        this.length = 0;
    }

    // 获取链表最大长度 (返回N即可)
    public int length() {
        return length;
    }

    // 判断链表是否为空(判断 N 是否 为 0 即可)
    public boolean isEmpty() {
        return length == 0;
    }

    //获取指定位置的元素 (用一个临时的结点指向头节点,不断让临时
    // 节点指向它的下一个结点)
    public T get(int i) {
        //通过循环,从头节点开始往后查找
        Node node = head;
        for (int j = 0; j <= i; j++) {
            node = node.next;
        }
        return node.item;
    }

    //向链表中 添加元素
    public void insert(T t) {
        //找到当前最后一个结点
        Node last = head;
        while (last.next != null) {
            last = last.next;
        }
        //创建新节点 保存元素t
        Node now = new Node(t, null);
        //让当前最后一个结点指向新的结点
        last.next = now;
        //然后让元素个数加一
        this.length++;
    }

    //向链表中的指定位置 添加元素
    public void insert(int i, T t) {
        Node pre = head;
        //找到i位置的前一个结点
        for (int j = 0; j < i; j++) {
            pre = pre.next;

        }
        //找到位置的结点
        Node cur = pre.next;
        //创建新结点 前一结点 指向新节点 新节点只想原来i 位置的结点
        Node now = new Node(t, cur);
        pre.next = now;
        //元素个数加一
        this.length++;
    }
    //删除指定位置元素
    public  T remove(int i) {
        //找到i位置前一个结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            head = pre.next;
        }
        //找到i 位置的节点并保存
        Node cur = pre.next;
        //找到 i 位置下一个节点
        Node next = cur.next;
        //前一个结点指向下一个结点
        pre.next =next;
        // 元素个数减一
        this.length--;
        return cur.item;
    }
    public int indexOf(T t){
        // 从头开始依次查找每一个节点,取出 item 和 t 比较,如果相同 则找到了
        Node now =head;
        for (int i = 0; now.next != null; i++) {
            now =now.next;
            if (now.item == t) {
                return i;
            }

        }
        //找不到就返回 -1;
        return - 1;
    }
}
  • 双链表
package com.codervibe.ch01;

public class TwoWayLinkList<T> {
    private Node head;
    private Node last;
    private int length;

    private class Node {
        public T item;
        //指向前一个结点
        public Node pre;
        //指向后一个结点
        public Node next;

        public Node(T item, Node pre, Node next) {
            this.item = item;
            this.pre = pre;
            this.next = next;
        }

    }

    //初始化头结点 尾结点指向null 初始链表长度为0
    public TwoWayLinkList() {
        //初始化 头节点和 尾结点
        this.head = new Node(null, null, null);
        this.last = null;
        //初始化元素的个数
        this.length = 0;
    }

    //清空链表(头节点,尾结点置空,链表长度置为零)
    public void clear() {
        this.head.next = null;
        this.last = null;
        this.length = 0;
    }

    //获取链表的长度
    public int length() {
        return this.length;
    }

    //判断链表是否为空
    public boolean isEmpty() {
        return length == 0;
    }

    //获取第一个元素
    public T getFileItem() {
        if (isEmpty()) {
            return null;
        }
        return head.next.item;
    }

    //获取第二个元素
    public T getLastItem() {
        if (isEmpty()) {
            return null;
        }
        return last.item;
    }

    public void insert(T t) {
        //如果链表为空
        if (isEmpty()) {
            //创建新节点,pre指向头节点
            Node newNode = new Node(t, head, null);
            // 让新节点 成为 尾结点
            last = newNode;
            //让头节点成为尾结点
            head.next = last;
        } else {
            // 如果不为空
            //创建新的结点
            Node newNode = new Node(t, last, null);
            //让当前尾结点指向新的结点
            last.next = newNode;
            //让新节点成为尾结点
            last = newNode;
        }
        //元素个数加一
        this.length++;
    }

    public void insert(int i, T t) {
        //找到i 位置的前一个结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            pre = pre.next;
        }
        //找到 i 的位置的结点
        Node cur = pre.next;
        //创建新节点,让其pre指向前一个结点,next 指向 i 位置结点
        Node newNode = new Node(t, pre, cur);
        //将前一个结点的next 变为新节点
        pre.next = newNode;
        // 让 i 位置的 pre 变为 新节点
        cur.pre = newNode;
        //元素个数 加一
        this.length++;

    }

    // 获取指定位置 元素
    public T getItem(int i) {
        //通过循环,从头节点 开始往后查找
        Node node = head;
        for (int j = 0; j < i; j++) {
            node = node.next;
        }
        return node.item;
    }
    // 获取指定元素的第一次出现的索引
    public int indexOf(T t) {
        //从头开始依次查找每一个结点,
        // 取出item 和 他比较,如果相同 则找到了 否则返回 -1

        Node now = head;
        for (int i = 0; now.next != null; i++) {
            now = now.next;
            if (now.item == t) {
                return i;
            }

        }
        //  找到不到就返回 -1
        return -1;
    }
    //删除指定元素并返回
    public T remove(int i){
        //找到前一个 结点
        Node pre = head;
        for (int j = 0; j < i; j++) {
            pre =pre.next;
        }
        //找到 i 位置的下一个结点
        Node cur = pre.next;
        //找到下一个结点
        Node nextNode = cur.next;
        //让前一个结点的next 指向下一个结点
        pre.next = nextNode;
        // 让下一个结点的pre 指向前一个结点
        nextNode.pre = pre;
        //元素个数减一
        this.length--;
        return cur.item;
    }


}
  • 测试 类
package com.codervibe.ch01;

import org.junit.Test;

public class LinkListTest {
    @Test
    public void OneWayLinkListTest() {
        OneWayLinkList<String> oneWayLinkList =new OneWayLinkList<>();
        oneWayLinkList.insert("孙悟空");
        oneWayLinkList.insert("猪八戒");
        oneWayLinkList.insert("貂蝉");
        oneWayLinkList.insert("吕布");
        oneWayLinkList.insert("老夫子");
        oneWayLinkList.insert("盘古");
        oneWayLinkList.insert("后羿");
        oneWayLinkList.insert("扁鹊");

        for (int i = 0; i < oneWayLinkList.length(); i++) {
            System.out.println(oneWayLinkList.get(i));
        }
        System.out.println("当前的链表长度为:" + oneWayLinkList.length());
        System.out.println("-------------------------------------");
        //测试获取
        String getLinkList = oneWayLinkList.get(5);
        System.out.println("获取索引的位置的结果为:"+getLinkList);
        //测试删除
        String removeItem= oneWayLinkList.remove(4);
        System.out.println("删除的元素为 " + removeItem+"\t"+"删除后的长度为"+ oneWayLinkList.length());
        //测试返回元素第一次出现的索引
        System.out.println("扁鹊 第一次出现的索引为 " + oneWayLinkList.indexOf("扁鹊"));
        //测试清空
        oneWayLinkList.clear();
        System.out.println("清空后链表中元素的个数为"+ oneWayLinkList.length());
    }
    @Test 
    public void TwoWayLinkListTest(){
        TwoWayLinkList<String> twoWayLinkList=new TwoWayLinkList<>();
        twoWayLinkList.insert("孙悟空");
        twoWayLinkList.insert("猪八戒");
        twoWayLinkList.insert("貂蝉");
        twoWayLinkList.insert("吕布");
        twoWayLinkList.insert("老夫子");
        twoWayLinkList.insert("盘古");
        twoWayLinkList.insert("后羿");
        twoWayLinkList.insert("扁鹊");
        for (int i = 0; i < twoWayLinkList.length(); i++) {
            System.out.println(twoWayLinkList.getItem(i));
        }
        System.out.println("当前列表的长度为:" + twoWayLinkList.length());
        System.out.println("----------------------------------------------------------");
        //测试获取
        System.out.println("获取索引位置的元素为" + twoWayLinkList.getItem(6));
        //测试删除
        System.out.println("删除的元素为  " + twoWayLinkList.remove(4)+ "删除后的 链表长度为:"+twoWayLinkList.length());
        //测试返回元素第一次出现的索引
        System.out.println("吕布 出现的 第一次索引为 " + twoWayLinkList.indexOf("吕布"));
        //测试在 指定索引的位置插入
        twoWayLinkList.insert(4,"李元芳");
        System.out.println("插入新元素之后 链表为");
        for (int i = 0; i < twoWayLinkList.length(); i++) {
            System.out.println(twoWayLinkList.getItem(i));
        }
        //测试清空链表 方法
        System.out.println("清空链表~~~");
        twoWayLinkList.clear();
        System.out.println("链表清空后的 的链表长度为 :" + twoWayLinkList.length());

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值