数据结构篇:链表

一、链表相关概念

1. 线性表、数组和链表
  • 线性表
    • 又称顺序表。线性表中的每一个数据称为一个元素,每个元素有且只有一个前驱元素。除了最后一个元素,每个元素有且仅有一个直接后继元素。
    • 数据元素之间的关系是一对一的关系。
  • 数组
    • 线性表的一种顺序存储方式。数组的内存是连续分配的,并且是静态分配的,即在使用数组之前需要分配固定大小的空间。
    • 可以通过索引直接得到数组中的元素,获取数组中元素的时间复杂度为O(1)
  • 链表
    • 线性表的一种链式存储结构。链表的内存不连续分配,并且是动态分配。
    • 链表通过一个指向下一个元素地址的引用将链表中的元素串起来。
2. 链表的分类
  • 单向链表
  • 双向链表
  • 单向循环链表
  • 双向循环链表

二、单向链表

1. 单向链表的组成
  • 单链表中的元素由数据域和Next指针域组成,各元素通过Next指针域连接。
  • 每个元素都存在后继元素(链尾除外)

单向链表

2. 单向链表的插入

单向链表的删除

3. 单向链表的删除

单向链表的删除

4. 单线链表的实现
/**
 * 单链表
 */
public class SingleLinkedList {

    // 头结点
    public SingleNode head;
    // 链表长度
    public int length;

    // 构造函数
    SingleLinkedList() {
        this.head = new SingleNode(null);
    }

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

    // 链表的长度
    public int length() {
        return length;
    }

    // 链表的新增(新增在链表尾部)
    public boolean add(int value) {
        SingleNode node = new SingleNode(value);
        SingleNode temp = head;
        while (null != temp.next) {
            temp = temp.next;
        }
        temp.next = node;
        length++;
        return true;
    }

    // 链表的新增(指定新增位置)
    public boolean addAt(int i, int value) {
        if (length < i){
            return false;
        }
        SingleNode node = new SingleNode(value);
        SingleNode temp = head;
        // 找到指定位置的前一个位置
        for (int k = 0; k < i - 1; k++) {
            temp = temp.next;
        }
        node.next = temp.next;
        temp.next = node;
        length++;
        return true;
    }

    // 链表的删除(指定位置)
    public boolean removeAt(int i) {
        if (length < i){
            return false;
        }
        SingleNode temp = head;
        // 找到待删除位置的前一个位置
        for (int k = 0; k < i - 1; k++){
            temp = temp.next;
        }
        temp.next = temp.next.next;
        length--;
        return true;
    }

    // 链表的删除(删除指定元素)
    public boolean remove(int value) {
        SingleNode temp = head;
        // 找到待删除位置的前一个位置
        while (null != temp.next){
            if (temp.next.value.equals(value)){
                temp.next = temp.next.next;
                length--;
                return true;
            }
            temp = temp.next;
        }
        return false;
    }

    // 链表的查找
    public SingleNode find(int i){
        if (i > length){
            return null;
        }
        SingleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        return temp;
    }

    // 链表的更新
    public boolean update(int i, int value){
        if (i > length){
            return false;
        }
        SingleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        temp.value = value;
        return true;
    }

    public void print(){
        SingleNode temp = head;
        while (null != temp.next){
            temp = temp.next;
            System.out.println(temp.value);
        }
    }

    public static class SingleNode {
        // 数据域
        Integer value;
        // 指针域
        SingleNode next;

        SingleNode(Integer value){
            this.value = value;
        }
    }

    // 测试类
    public static void main(String[] args){
        SingleLinkedList list = new SingleLinkedList();
        list.add(3);
        list.add(2);
        list.add(4);
        list.addAt(3, 5);
        list.remove(7);
        list.removeAt(5);
        list.remove(3);
        list.removeAt(1);
        SingleNode singleNode = list.find(1);
        list.update(2, 6);
        list.print();
    }

}

三、双向链表

1. 双向链表的组成
  • 双链表的元素由数据域、Prev指针域和Next指针域组成,各元素通过Prev指针域和Next指针域链接。
  • 每个元素都存在前驱元素和后继元素(链头没有前驱,链尾没有后继)

双向链表的组成

2. 双向链表的插入

双向链表的插入

3. 双向链表的删除

双向链表的删除

4. 双向链表的实现
/**
 * 双链表
 */
public class DoubleLinkedList {

    // 头结点
    public DoubleNode head;
    // 链表长度
    public int length;

    DoubleLinkedList() {
        this.head = new DoubleNode(null);
    }

    public boolean isEmpty() {
        return length == 0;
    }

    public int length() {
        return length;
    }

    // 新增元素(默认放置尾部)
    public boolean add(int value) {
        DoubleNode node = new DoubleNode(value);
        DoubleNode temp = head;
        while (null != temp.next) {
            temp = temp.next;
        }
        temp.next = node;
        node.pre = temp;
        length++;
        return true;
    }

    // 新增元素(指定新增位置)
    public boolean addAt(int i, int value) {
        if (i > length){
            return false;
        }
        // 找到新增位置的前一个位置
        DoubleNode node = new DoubleNode(value);
        DoubleNode temp = head;
        for (int k = 0; k < i - 1; k++){
            temp = temp.next;
        }
        node.next = temp.next;
        temp.next.pre = node;
        node.pre = temp;
        temp.next = node;
        length++;
        return true;
    }

    // 删除元素(指定位置)
    public boolean removeAt(int i){
        if (i > length){
            return false;
        }
        // 查找待删除的位置
        DoubleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        temp.pre.next = temp.next;
        temp.next.pre = temp.pre;
        length--;
        return true;
    }

    // 删除元素
    public boolean remove(int value){
        DoubleNode temp = head;
        // 查找待删除的位置
        while (null != temp.next){
            temp = temp.next;
            if (temp.value == value){
                temp.pre.next = temp.next;
                temp.next.pre = temp.pre;
                length--;
                return true;
            }
        }
        return false;
    }

    // 链表的查找
    public DoubleNode find(int i){
        if (i > length){
            return null;
        }
        DoubleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        return temp;
    }

    // 链表的更新
    public boolean update(int i, int value){
        if (i > length){
            return false;
        }
        DoubleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        temp.value = value;
        return true;
    }

    public void print(){
        DoubleNode temp = head;
        while (null != temp.next){
            temp = temp.next;
            System.out.println(temp.value);
        }
    }

    public static class DoubleNode {
        // 数据域
        Integer value;
        // 前指针域
        DoubleNode pre;
        // 后指针域
        DoubleNode next;

        DoubleNode(Integer value){
            this.value = value;
        }
    }

    // 测试类
    public static void main(String[] args){
        DoubleLinkedList list = new DoubleLinkedList();
        list.add(3);
        list.add(2);
        list.add(4);
        list.addAt(3, 5);
        list.remove(7);
        list.removeAt(5);
        list.remove(3);
        list.removeAt(1);
        DoubleNode singleNode = list.find(1);
        list.update(2, 6);
        list.print();
    }

}

四、单向循环链表

1. 单向循环链表的组成
  • 单链表中的元素由数据域和Next指针域组成,各元素通过Next指针域连接。
  • 每个元素都存在后继元素(包括链尾)

单向循环链表

2. 单向循环链表的插入

单向循环链表的插入

3. 单向循环链表的删除

单向循环链表的删除

4. 单向循环链表的实现
/**
 * 单向循环链表
 */
public class SingleCycleLinkedList {

    // 头结点
    public SingleCyleNode head;
    // 尾结点
    public SingleCyleNode tail;
    // 链表长度
    public int length;

    SingleCycleLinkedList(){
        this.head = new SingleCyleNode(null);
        this.tail = new SingleCyleNode(null);
        head.next = tail;
        tail.next = head;
    }

    public boolean isEmpty(){
        return length == 0;
    }

    public int length(){
        return length;
    }

    // 链表的新增(新增在链表尾部)
    public boolean add(int value) {
        SingleCyleNode node = new SingleCyleNode(value);
        SingleCyleNode temp = head;
        while (tail != temp.next) {
            temp = temp.next;
        }
        temp.next = node;
        node.next = tail;
        length++;
        return true;
    }

    // 链表的新增(指定新增位置)
    public boolean addAt(int i, int value) {
        if (length < i){
            return false;
        }
        SingleCyleNode node = new SingleCyleNode(value);
        SingleCyleNode temp = head;
        // 找到指定位置的前一个位置
        for (int k = 0; k < i - 1; k++) {
            temp = temp.next;
        }
        node.next = temp.next;
        temp.next = node;
        length++;
        return true;
    }

    // 链表的删除(指定位置)
    public boolean removeAt(int i) {
        if (length < i){
            return false;
        }
        SingleCyleNode temp = head;
        // 找到待删除位置的前一个位置
        for (int k = 0; k < i - 1; k++){
            temp = temp.next;
        }
        temp.next = temp.next.next;
        length--;
        return true;
    }

    // 链表的删除(删除指定元素)
    public boolean remove(int value) {
        SingleCyleNode temp = head;
        // 找到待删除位置的前一个位置
        while (tail != temp.next){
            if (temp.next.value == value){
                temp.next = temp.next.next;
                length--;
                return true;
            }
            temp = temp.next;
        }
        return false;
    }

    // 链表的查找
    public SingleCyleNode find(int i){
        if (i > length){
            return null;
        }
        SingleCyleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        return temp;
    }

    // 链表的更新
    public boolean update(int i, int value){
        if (i > length){
            return false;
        }
        SingleCyleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        temp.value = value;
        return true;
    }

    public void print(){
        SingleCyleNode temp = head;
        while (tail != temp.next){
            temp = temp.next;
            System.out.println(temp.value);
        }
    }

    public static class SingleCyleNode {
        // 数据域
        Integer value;
        // 指针域
        SingleCyleNode next;

        SingleCyleNode(Integer value){
            this.value = value;
        }
    }

    // 测试类
    public static void main(String[] args){
        SingleCycleLinkedList list = new SingleCycleLinkedList();
        list.add(3);
        list.add(2);
        list.add(4);
        list.addAt(3, 5);
        list.remove(7);
        list.removeAt(5);
        list.remove(3);
        list.removeAt(1);
        SingleCyleNode singleNode = list.find(1);
        list.update(2, 6);
        list.print();
    }

}

五、双向循环链表

1. 双向循环链表的组成
  • 双链表的元素由数据域、Prev指针域和Next指针域组成,各元素通过Prev指针域和Next指针域链接。
  • 每个元素都存在前驱元素和后继元素(包括链头和链尾)

双向循环链表

2. 双向循环链表的插入

双向循环链表的插入

3. 双向循环链表的删除

双向循环链表的删除

4. 双向循环链表的实现
/**
 * 双向循环链表
 */
public class DoubleCycleLinkedList {

    // 头结点
    public DoubleCycleNode head;
    // 尾结点
    public DoubleCycleNode tail;
    // 链表长度
    public int length;

    DoubleCycleLinkedList(){
        this.head = new DoubleCycleNode(null);
        this.tail = new DoubleCycleNode(null);
        head.next = tail;
        head.pre = tail;
        tail.next = head;
        tail.pre = head;
    }

    // 链表的新增(新增在链表尾部)
    public boolean add(int value) {
        DoubleCycleNode node = new DoubleCycleNode(value);
        DoubleCycleNode temp = head;
        while (tail != temp.next) {
            temp = temp.next;
        }
        temp.next = node;
        node.pre = temp;
        tail.pre = node;
        node.next = tail;
        length++;
        return true;
    }

    // 链表的新增(指定新增位置)
    public boolean addAt(int i, int value) {
        if (length < i){
            return false;
        }
        DoubleCycleNode node = new DoubleCycleNode(value);
        DoubleCycleNode temp = head;
        // 找到指定位置的前一个位置
        for (int k = 0; k < i - 1; k++) {
            temp = temp.next;
        }
        node.next = temp.next;
        temp.next = node;
        length++;
        return true;
    }

    // 链表的删除(指定位置)
    public boolean removeAt(int i) {
        if (length < i){
            return false;
        }
        DoubleCycleNode temp = head;
        // 找到待删除位置的前一个位置
        for (int k = 0; k < i - 1; k++){
            temp = temp.next;
        }
        temp.next = temp.next.next;
        length--;
        return true;
    }

    // 链表的删除(删除指定元素)
    public boolean remove(int value) {
        DoubleCycleNode temp = head;
        // 找到待删除位置的前一个位置
        while (tail != temp.next){
            if (temp.next.value == value){
                temp.next = temp.next.next;
                length--;
                return true;
            }
            temp = temp.next;
        }
        return false;
    }

    // 链表的查找
    public DoubleCycleNode find(int i){
        if (i > length){
            return null;
        }
        DoubleCycleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        return temp;
    }

    // 链表的更新
    public boolean update(int i, int value){
        if (i > length){
            return false;
        }
        DoubleCycleNode temp = head;
        for (int k = 0; k < i; k++){
            temp = temp.next;
        }
        temp.value = value;
        return true;
    }

    public void print(){
        DoubleCycleNode temp = head;
        while (tail != temp.next){
            temp = temp.next;
            System.out.println(temp.value);
        }
    }

    public static class DoubleCycleNode{
        // 数据域
        Integer value;
        // 前指针域
        DoubleCycleNode pre;
        // 后指针域
        DoubleCycleNode next;

        DoubleCycleNode(Integer value){
            this.value = value;
        }
    }

    // 测试类
    public static void main(String[] args){
        DoubleCycleLinkedList list = new DoubleCycleLinkedList();
        list.add(3);
        list.add(2);
        list.add(4);
        list.addAt(3, 5);
        list.remove(7);
        list.removeAt(5);
        list.remove(3);
        list.removeAt(1);
        DoubleCycleNode singleNode = list.find(1);
        list.update(2, 6);
        list.print();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值