数据结构&算法Java版(一) 链表

欢迎关注我的B站账号:卍卍子非鱼卍卍

链表

单链表

链表节点LinkedNode

// 链表节点LinkedNode
class LinkedNode<T> {
    public T val;
    public LinkedNode<T> next;

    public LinkedNode() {
        this(null);
    }

    public LinkedNode(T val) {
        this.val = val;
        this.next = null;
    }
}

链表MyLinkedList

LinkedNode<T> getHead() 获取表头

boolean isEmpty() 判断链表是否为空

void add(T val) 向链表末尾添加元素

void add(int index, T val) 向链表指定位置添加元素

T remove() 移除链表末尾元素

T remove(int index) 移除链表指定位置元素

T get(int index) 获取链表指定位置元素

int size() 获取链表长度

String toString() 输出链表

class MyLinkedList<T> {
    public LinkedNode<T> head;

    public MyLinkedList() {
        this.head = new LinkedNode<T>();
        head.next = null;
    }

    // 获取表头
    public LinkedNode<T> getHead() {
        if (this.isEmpty()) {
            throw new NullPointerException();
        }
        return head.next;
    }

    // 判断链表是否为空
    public boolean isEmpty() {
        return head.next == null;
    }

    // 向链表末尾添加元素
    public void add(T val) {
        this.add(this.size(), val);
    }

    // 向链表指定位置添加元素
    public void add(int index, T val) {
        if (index < 0 || index > this.size()) {
            throw new NullPointerException();
        }
        LinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        LinkedNode<T> node = new LinkedNode<T>(val);
        node.next = p.next;
        p.next = node;
    }

    // 移除链表末尾元素
    public T remove() {
        return this.remove(this.size() - 1);
    }

    // 移除链表指定位置元素
    public T remove(int index) {
        if (index < 0 || index >= this.size()) {
            throw new NullPointerException();
        }
        LinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        T val = p.next.val;
        p.next = p.next.next;
        return val;
    }

    // 获取链表指定位置元素
    public T get(int index) {
        if (index < 0 || index >= this.size()) {
            throw new NullPointerException();
        }
        LinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        return p.next.val;
    }

    // 获取链表长度
    public int size() {
        LinkedNode<T> p = head;
        int n = 0;
        while (p.next != null) {
            p = p.next;
            n++;
        }
        return n;
    }

    // 输出链表
    public String toString() {
        LinkedNode<T> p = head;
        String str = "";
        if (p.next == null) {
            return "";
        }
        while (p.next.next != null) {
            p = p.next;
            str += p.val + "->";
        }
        str += p.next.val;
        return str;
    }
}

双链表

双链表节点DlinkedNode

class DLinkedNode<T> {
    public T val;
    public DLinkedNode<T> next;
    public DLinkedNode<T> pre;

    public DLinkedNode() {
        this(null);
    }

    public DLinkedNode(T val) {
        this.val = val;
        this.next = null;
        this.pre = null;
    }
}

双链表MyDLinkedList

DLinkedNode<T> getHead() 获取表头

boolean isEmpty() 判断链表是否为空

void add(T val) 向链表末尾添加元素

void add(int index, T val) 向链表指定位置添加元素

T remove() 移除链表末尾元素

T remove(int index) 移除链表指定位置元素

T get(int index) 获取链表指定位置元素

int size() 获取链表长度

String toString() 输出链表

class MyDLinkedList<T> {
    public DLinkedNode<T> head;

    public MyDLinkedList() {
        this.head = new DLinkedNode<T>();
    }

    // 获取表头
    public DLinkedNode<T> getHead() {
        return head.next;
    }

    // 判断链表是否为空
    public boolean isEmpty() {
        return head.next == null;
    }

    // 向链表末尾添加元素
    public void add(T val) {
        this.add(this.size(), val);
    }

    // 向链表指定位置添加元素
    public void add(int index, T val) {
        if (index < 0 || index > this.size()) {
            throw new NullPointerException();
        }
        DLinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        DLinkedNode<T> node = new DLinkedNode<T>(val);
        node.next = p.next;
        if (p.next != null) {
            p.next.pre = node;
        }
        p.next = node;
        node.pre = p;
    }

    // 移除链表末尾元素
    public T remove() {
        return this.remove(this.size() - 1);
    }

    // 移除链表指定位置元素
    public T remove(int index) {
        if (index < 0 || index >= this.size()) {
            throw new NullPointerException();
        }
        DLinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        DLinkedNode<T> node = p.next;
        p.next = p.next.next;
        if (p.next != null) {
            p.next.pre = p;
        }
        return node.val;
    }

    // 获取链表指定位置元素
    public T get(int index) {
        if (index < 0 || index >= this.size()) {
            throw new NullPointerException();
        }
        DLinkedNode<T> p = head;
        int n = 0;
        while (n < index) {
            p = p.next;
            n++;
        }
        return p.next.val;
    }

    // 获取链表长度
    public int size() {
        DLinkedNode<T> p = head;
        int n = 0;
        while (p.next != null) {
            p = p.next;
            n++;
        }
        return n;
    }

    // 输出链表
    public String toString() {
        DLinkedNode<T> p = head;
        String str = "";
        if (p.next == null) {
            return "";
        }
        while (p.next.next != null) {
            p = p.next;
            str += p.val + "<->";
        }
        str += p.next.val;
        return str;
    }
}

链表排序

输入待排序链表头节点,输出排序后链表头节点

算法思路

现有如下链表:

将其进行升序排序:

思路如下:

1.定义虚拟头节点preHead,将其next指针指向真正的头节点head
在这里插入图片描述
2.定义指针p指向preHead,指针q指向链表中的第二个节点,并切断第一,二个节点之间的连接
在这里插入图片描述
3.当q != null时,进行循环:

4.用临时指针temp指向q.next,指针p指向preHead, 当p指针指向的下一个节点的值小于等于q指针指向节点的值,即p.next.val <= q.val时,p指针向右移动。直到下一个节点的值大于q指针指向节点的值或到达表尾。
在这里插入图片描述
5.此时说明q节点应插入p节点之后
在这里插入图片描述
6.令q = temp,返回第3步
在这里插入图片描述
7.循环结束,返回preHead.next

代码

/**
 * 链表排序
 * 
 * @param head 待排序链表头节点
 * @return 排序后链表头节点
 */
public LinkedNode<Integer> sort(LinkedNode<Integer> head) {
    if (head == null) {
        return null;
    }
    LinkedNode<Integer> preHead = new LinkedNode<Integer>(-1);
    preHead.next = head;
    LinkedNode<Integer> p = preHead, q = head.next;
    head.next = null;
    while (q != null) {
        LinkedNode<Integer> temp = q.next;
        p = preHead;
        while (p.next != null && p.next.val <= q.val) {
            p = p.next;
        }
        q.next = p.next;
        p.next = q;
        q = temp;
    }
    return preHead.next;
}

合并有序链表

输入两个有序链表头节点,输出合并后的链表头节点

算法思路

两个有序链表:
在这里插入图片描述
将其合并为一个有序链表:
在这里插入图片描述
思路如下:

1.定义指针p1p2分别指向两个链表的表头,定义虚拟头节点preHead,定义遍历指针index指向preHead
在这里插入图片描述
2.当p1p2至少有一个不为null时,进行循环:

3.首先判断其中一个是否为null,若其中一个为nullindex节点的next指针就指向另一个不为null的节点,并结束循环
在这里插入图片描述
4.若p1p2均不为null,比较两节点的值,令index节点的next指针指向小的那一方,并且让对应的指针(p1p2)向右移动,最后,让index指针也向右移动
在这里插入图片描述
5.返回第2步

6.循环结束,返回preHead.next

代码

/**
 * 合并有序链表
 * 
 * @param LA 有序链表头节点
 * @param LB 有序链表头节点
 * @return 合并后的链表头节点
 */
public LinkedNode<Integer> UnionList(LinkedNode<Integer> LA, LinkedNode<Integer> LB) {
    LinkedNode<Integer> p1 = LA, p2 = LB;
    LinkedNode<Integer> preHead = new LinkedNode<Integer>(-1);
    LinkedNode<Integer> index = preHead;
    while (p1 != null || p2 != null) {
        if (p1 == null) {
            index.next = p2;
            break;
        } else if (p2 == null) {
            index.next = p1;
            break;
        } else {
            if (p1.val < p2.val) {
                index.next = p1;
                p1 = p1.next;
            } else {
                index.next = p2;
                p2 = p2.next;
            }
        }
        index = index.next;
    }
    return preHead.next;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值