数据结构《链表》

news2024/12/23 12:17:58

文章目录

  • 前言
  • 一、什么是链表?
  • 二、单向链表
    • 2.1 单向链表的个人实现
    • 2.2 单向链表的例题
  • 三、双向链表
    • 3.1 双向链表的个人实现
    • 3.2 关于真正的java中提供的链表的使用
  • 总结


前言

提示:概念来源于:>>LinkedList<<


一、什么是链表?

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

链表可分为单向链表和双向链表。

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。


二、单向链表

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
在这里插入图片描述

2.1 单向链表的个人实现

先定义一个接口,让个人实现的单向链表实现这个接口中的方法,感兴趣可以直接复制这段代码,然后自己试试实现。

public interface ILinkedList {
    //头插法
    public void addFirst(int data);
    //尾插法
    public void addLast(int data);
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data);
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key);
    //删除第一次出现关键字为key的节点
    public void remove(int key);
    //删除所有值为key的节点
    public void removeAllKey(int key);
    //得到单链表的长度
    public int size();
    //用来显示自己的链表,便于编写代码
    public void display();
    //清空链表
    public void clear();
}


display() — 显示链表中所有内容

//显示链表中所有内容
	public void display() {
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
    }

在这里插入图片描述

在这里插入图片描述


size() — 得到单链表的长度

//得到单链表的长度
    public int size() {
        ListNode cur = head;
        int size = 0;
        while (cur != null){
            size++;
            cur = cur.next;
        }
        return size;
    }

和上面的显示链表相似,就是遍历链表


定义一个私有方法,专门用来判断是不是空链表

	private boolean isEmpty(MySingleLinkedList mySingleLinkedList){
        return 0 == mySingleLinkedList.size();
    }

addFirst() — 头插法

//头插法
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        node.next = head;
        head = node;
    }

在这里插入图片描述

在这里插入图片描述


addLast(int data) — 尾插法

//尾插法
    public void addLast(int data) {
        ListNode node = new ListNode(data);
        if (isEmpty(this)){
            head = node;
            return;   //要记得加
        }
        ListNode cur = head;
        while (null != cur.next){
            cur = cur.next;
        }
        cur.next = node;
    }

在这里插入图片描述

在这里插入图片描述


contains() — 查找是否包含关键字key

//查找是否包含关键字key是否在单链表当中
 public boolean contains(int key) {
        ListNode cur = head;
        while (cur != null){
            if(key == cur.val){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

同样是遍历链表,查找到就返回true,找不到就返回false


addIndex() — 任意位置插入

//任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index, int data) {
        int len = size();
        if(index < 0 || index > len){
            System.out.println("输入错误");
            return;
        }
        ListNode node = new ListNode(data);
        if(0 == index){
            addFirst(data);
            return;
        }
        if (len - 1 == index){
            addLast(data);
            return;
        }
        ListNode cur = head;
        while (0 != index - 1){
            cur = cur.next;
            index--;
        }
        node.next = cur.next;
        cur.next = node;
    }

这里分了三种情况,当插入位置是0,既是头插,当插入位置为节点的长度-1时,则是尾插,其余部分是中间插入,头插和尾插直接调用上面的方法即可,这里介绍中间插入。
在这里插入图片描述
在这里插入图片描述


remove() — 删除第一次出现关键字为key的节点

//删除第一次出现关键字为key的节点
    public void remove(int key) {
        if(isEmpty(this)){
            System.out.println("空链表无法使用");
        }
        if(key == head.val){
            head = head.next;
            return;
        }
        ListNode cur = head;
        while (null != cur.next){
            if(key != cur.next.val){
                cur = cur.next;
            }else {
                ListNode del = cur.next;
                if (null != del.next) {
                    cur.next = del.next;
                }else {
                    cur.next = null;
                }
                return;
            }
        }
        System.out.println("没有要删除的选项");
    }

删除也分为三个可能,头删,中间删,尾删,因为我们val里放的是一个基本变量,不用担心空间的释放,因为没有引用变量来引用这个对象,比如如果我们放的是一个自己定义的学生对象,我们就需要将val置为空,而这里我们只需要让被删除的节点不被前后节点指向就是删除了。

头删很简单,直接让头节点指向头节点的下一个节点即可。

接下来我们主要考虑,中间的删除和尾删。

中间删除
在这里插入图片描述
在这里插入图片描述
尾删除
这个很简单,在中间删除进行判断中,如果del的next为空,说明我们要删除最后一个节点,直接将cur.next置为空即可
在这里插入图片描述


removeAllKey() — 删除所有值为key的节点

 //删除所有值为key的节点
    public void removeAllKey(int key) {
        ListNode cur = head;
        if(head == null){
            return;
        }
        while (head !=null && key == head.val){
            head = head.next;
        }
        ListNode del = cur;
        while (null != cur.next){
            if(key == cur.next.val){
                del = cur.next;
                cur.next = del.next;
            }else {
                cur = cur.next;
            }
        }
    }

这里和上面的删除第一个值为key的节点很相似,只是把原来在遇到后删除直接返回,变成了遍历整个链表,反复执行删除操作,上面的代码理解了,可以很容易看懂,这里不多赘述了。


clear() — 清空链表

//清空链表
public void clear() {
        ListNode cur;
        while (null != head.next){
            cur = head;
            head = head.next;
            cur.next = null;
        }
        head = null;
    }

这个就简单了,这里也可以将value置为空,因为我们是整数类型,不用担心内存浪费的问题,直接将head一直往后置空就好,就相当于在删除了。


最后是整个自定义单向无头链表的实现代码整合

public class MySingleLinkedList implements ILinkedList{
    static class ListNode{
        public int val;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head;
    @Override
    public void display() {
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
    }

    @Override
    //得到单链表的长度
    public int size() {
        ListNode cur = head;
        int size = 0;
        while (cur != null){
            size++;
            cur = cur.next;
        }
        return size;
    }

    @Override
    查找是否包含关键字key是否在单链表当中
    public boolean contains(int key) {
        ListNode cur = head;
        while (cur != null){
            if(key == cur.val){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    private boolean isEmpty(MySingleLinkedList mySingleLinkedList){
        return 0 == mySingleLinkedList.size();
    }

    @Override
    //头插法
    public void addFirst(int data) {
        ListNode node = new ListNode(data);
        node.next = head;
        head = node;
    }

    @Override
    //尾插法
    public void addLast(int data) {
        ListNode node = new ListNode(data);
        if (isEmpty(this)){
            head = node;
            return;   //要记得加
        }
        ListNode cur = head;
        while (null != cur.next){
            cur = cur.next;
        }
        cur.next = node;
    }

    @Override
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index, int data) {
        int len = size();
        if(index < 0 || index > len){
            System.out.println("输入错误");
            return;
        }
        ListNode node = new ListNode(data);
        if(0 == index){
            addFirst(data);
            return;
        }
        if (len - 1 == index){
            addLast(data);
            return;
        }
        ListNode cur = head;
        while (0 != index - 1){
            cur = cur.next;
            index--;
        }
        node.next = cur.next;
        cur.next = node;
    }


    @Override
    //删除第一次出现关键字为key的节点
    public void remove(int key) {
        if(isEmpty(this)){
            System.out.println("空链表无法使用");
        }
        if(key == head.val){
            head = head.next;
            return;
        }
        ListNode cur = head;
        while (null != cur.next){
            if(key != cur.next.val){
                cur = cur.next;
            }else {
                ListNode del = cur.next;
                if (null != del.next) {
                    cur.next = del.next;
                }else {
                    cur.next = null;
                }
                return;
            }
        }
        System.out.println("没有要删除的选项");
    }

    @Override
    //删除所有值为key的节点
    public void removeAllKey(int key) {
        ListNode cur = head;
        if(head == null){
            return;
        }
        while (head !=null && key == head.val){
            head = head.next;
        }
        ListNode del = cur;
        while (null != cur.next){
            if(key == cur.next.val){
                del = cur.next;
                cur.next = del.next;
            }else {
                cur = cur.next;
            }
        }
    }

    @Override
    public void clear() {
        ListNode cur;
        while (null != head.next){
            cur = head;
            head = head.next;
            cur.next = null;
        }
        head = null;
    }
   
}


2.2 单向链表的例题

例题1.反转链表
在这里插入图片描述

public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode newNode = cur.next;
            cur.next = pre;
            pre = cur;
            cur = newNode;
        }
    return pre;
    }

例题2. 链表的中间节点

快慢指针

在这里插入图片描述

public ListNode middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

例题3. 合并两个有序链表

在这里插入图片描述

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null){
            return list2;
        }
        if(list2 == null){
            return list1;
        }
        ListNode head = new ListNode();
        ListNode cur = head;
        while(list1 != null && list2 != null){
            if(list1.val <= list2.val){
                cur.next = list1;
                list1 = list1.next;
            }else{
                cur.next = list2;
                list2 = list2.next;
            }
            cur = cur.next;
        }
        if(list1 != null){
            cur.next = list1;
        }
        if(list2 != null){
            cur.next = list2;
        }
        return head.next;
    }

例题4. 链表分割
在这里插入图片描述

public ListNode partition(ListNode pHead, int x) {
        // write code here
        ListNode lb = null;
        ListNode le = null;
        ListNode bb = null;
        ListNode be = null;

        ListNode cur = pHead;
        if(cur == null){
            return pHead;
        }
        while(cur != null){
            if(cur.val < x){
                if(lb == null){
                    lb = cur;
                    le = cur;
                }else{
                    le.next = cur;
                    le = cur;
                }
            }else{
                if(bb == null){
                    bb = cur;
                    be = cur;
                }else{
                    be.next = cur;
                    be = cur;
                }
            }
            cur = cur.next;
        }
        if(lb != null){
            le.next = bb;
        }else{
            return bb;
        }
        if(bb != null){
            be.next = null;
        }
        return lb;

    }

例题5. 链表的回文结构

在这里插入图片描述

public boolean chkPalindrome(ListNode A) {
        // write code here
        if (A == null) {
            return false;
        }
        ListNode head = A;
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode cur = slow.next;

        while (cur != null) {
            ListNode curN = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curN;
        }
        while (head != slow) {
            if (head.next == slow) {
                return head.val == slow.val;
            }
            if (head.val != slow.val) {
                return false;
            } else {
                head = head.next;
                slow = slow.next;
            }
        }
        while (head != slow) {
            if (head.next == slow) {
                return head.val == slow.val;
            }
            if (head.val != slow.val) {
                return false;
            } else {
                head = head.next;
                slow = slow.next;
            }
        }
        return true;
    }

例题6. 相交链表
在这里插入图片描述

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode cur1 = headA;
        ListNode cur2 = headB;
        int count1 = 0;
        int count2 = 0;
        while(cur1 != null){
            count1++;
            cur1 = cur1.next;
        }
        while(cur2 != null){
            count2++;
            cur2 = cur2.next;
        }
        cur1 = headA;
        cur2 = headB;
        if(count1 < count2){
            int m = count2 - count1;
            while(m != 0){
                cur2 = cur2.next;
                m--;
            }
        }else{
            int m = count1 - count2;
            while(m != 0){
                cur1 = cur1.next;
                m--;
            }
        }
        
        while(cur1 != null){
            if(cur1 == cur2){
                return cur1;
            }else{
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
        }
        return null;
    }

例题7. 环形链表
在这里插入图片描述

public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast != slow){
            if(fast == null || fast.next == null){
                return false;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        return true;
    }

三、双向链表

一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。

在这里插入图片描述
与单向链表不同的是,我们需要两个域来分别记录前一个节点的位置和后一个节点的位置。

3.1 双向链表的个人实现

双向链表的实现和单向链表的实现其实并不会差很多,只是我们要考虑一个节点的关于前后节点的引用。所以解析会相对简单。
同样的,通过接口来规范化我们定义的双向链表

public interface ILinkedList {
        //头插法
        public void addFirst(int data);
        //尾插法
        public void addLast(int data);
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data);
        //查找是否包含关键字key是否在单链表当中
        public boolean contains(int key);
        //删除第一次出现关键字为key的节点
        public void remove(int key);
        //删除所有值为key的节点
        public void removeAllKey(int key);
        //得到单链表的长度
        public int size();
        public void display();
        public void clear();

}


display() — 展示链表内容

public void display() {
        ListNode cur = head;
        while (null != cur){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }

    }

size() — 链表长度

public int size() {
        int size = 0;
        ListNode cur = head;
        while (null != cur){
            size++;
            cur = cur.next;
        }
        return size;
    }

addFirst() — 头插法

public void addFirst(int data) {
        ListNode first = new ListNode(data);
        if(null == this.head){
            this.head = first;
            this.last = first;
        }else {
            first.next = this.head;
            this.head.pre = first;
            this.head = first;
        }
    }

在这里插入图片描述


addLast() — 尾插法

public void addLast(int data) {
        ListNode nlast = new ListNode(data);
        if(null == this.head){
            this.head = nlast;
            this.last = nlast;
        }else {
            this.last.next = nlast;
            nlast.pre = this.last;
            this.last = nlast;
        }
    }

因为我们有一个last引用专门用来指向尾节点,所以,我们直接可以用last来插入即可。


addIndex() — 按位置插入

public void addIndex(int index, int data) {
        try {
            if(index < 0 || index > size()){
                throw new ErrorIndexException("错误的位置!!");//这是自定义的异常
            }
            if(0 == index){
                addFirst(data);
                return;
            }//头插法
            if (size() == index){
                addLast(data);
                return;
            }//尾插法
            ListNode cur = head;
            while (index - 1 != 0){
                cur = cur.next;
                index--;
            }
            ListNode node = new ListNode(data);
            node.next = cur.next;
            node.pre = cur.next.pre;
            cur.next.pre = node;
            cur.next = node;
        }catch (ErrorIndexException e){
            e.printStackTrace();
        }

    }

在这里插入图片描述


contains() — 是否包含某个数

public boolean contains(int key) {
        ListNode cur = head;

        while (null != cur){
            if (key == cur.val){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

remove() — 删除某数

public void remove(int key) {
        ListNode cur = head;
        while (null != cur){
            if(key == cur.val){
                if(cur == head){
                    head = head.next;
                    head.pre = null;
                    return;
                }
                if(cur == last){
                    last = last.pre;
                    last.next = null;
                    return;
                }
                cur.next.pre = cur.pre;
                cur.pre.next = cur.next;
                return;
            }
            cur = cur.next;
        }
        System.out.println("没有所要删除的数字");
    }

在这里插入图片描述
我们分为三种情况,删除的为头节点,尾节点,和中间的。


removeAllKey() — 删除所有的数为目标数的节点

public void removeAllKey(int key) {
        ListNode cur = head;
        while (null != cur){
            if(key == cur.val){
                if(cur == head){
                    head = head.next;
                    cur = head;
                    continue;
                }
                if(cur == last){
                    last = last.pre;
                    last.next = null;
                    cur = last;
                    continue;
                }
                if(cur.next != null && cur.pre != null){
                    ListNode curN = cur;
                    curN.next.pre = curN.pre;
                    curN.pre.next = curN.next;
                    cur = curN.next;
                    continue;
                }
            }
            cur = cur.next;
        }
    }

与上面的删除某个节点不同的是我们需要记录被删除的点(用curN记录),便于我们可以继续遍历链表。


clear() — 清空链表

public void clear() {
        while (null != head){
            ListNode headN = head;
            head = head.next;
            headN = null;
        }
        head = null;
    }

最后是整个个人实现链表的代码整合

public class MyLinkedList implements ILinkedList{
    static class ListNode{
        private final int val;
        private ListNode pre;
        private ListNode next;
        public ListNode(int val) {
            this.val = val;
        }
    }
    private ListNode head;
    private ListNode last;

    @Override
    public void addFirst(int data) {
        ListNode first = new ListNode(data);
        if(null == this.head){
            this.head = first;
            this.last = first;
        }else {
            first.next = this.head;
            this.head.pre = first;
            this.head = first;
        }
    }

    @Override
    public void addLast(int data) {
        ListNode nlast = new ListNode(data);
        if(null == this.head){
            this.head = nlast;
            this.last = nlast;
        }else {
            this.last.next = nlast;
            nlast.pre = this.last;
            this.last = nlast;
        }
    }

    @Override
    public void addIndex(int index, int data) {
        try {
            if(index < 0 || index > size()){
                throw new ErrorIndexException("错误的位置!!");
            }
            if(0 == index){
                addFirst(data);
                return;
            }
            if (size() == index){
                addLast(data);
                return;
            }
            ListNode cur = head;
            while (index - 1 != 0){
                cur = cur.next;
                index--;
            }
            ListNode node = new ListNode(data);
            node.next = cur.next;
            node.pre = cur.next.pre;
            cur.next.pre = node;
            cur.next = node;
        }catch (ErrorIndexException e){
            e.printStackTrace();
        }

    }

    @Override
    public boolean contains(int key) {
        ListNode cur = head;

        while (null != cur){
            if (key == cur.val){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    @Override
    public void remove(int key) {
        ListNode cur = head;
        while (null != cur){
            if(key == cur.val){
                if(cur == head){
                    head = head.next;
                    head.pre = null;
                    return;
                }
                if(cur == last){
                    last = last.pre;
                    last.next = null;
                    return;
                }
                cur.next.pre = cur.pre;
                cur.pre.next = cur.next;
                return;
            }
            cur = cur.next;
        }
        System.out.println("没有所要删除的数字");
    }

    @Override
    public void removeAllKey(int key) {
        ListNode cur = head;
        while (null != cur){
            if(key == cur.val){
                if(cur == head){
                    head = head.next;
                    cur = head;
                    continue;
                }
                if(cur == last){
                    last = last.pre;
                    last.next = null;
                    cur = last;
                    continue;
                }
                if(cur.next != null && cur.pre != null){
                    ListNode curN = cur;
                    curN.next.pre = curN.pre;
                    curN.pre.next = curN.next;
                    cur = curN.next;
                    continue;
                }
            }
            cur = cur.next;
        }
    }

    @Override
    public int size() {
        int size = 0;
        ListNode cur = head;
        while (null != cur){
            size++;
            cur = cur.next;
        }
        return size;
    }

    @Override
    public void display() {
        ListNode cur = head;
        while (null != cur){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }

    }

    @Override
    public void clear() {
        while (null != head){
            ListNode headN = head;
            head = head.next;
            headN = null;
        }
        head = null;
    }
}

3.2 关于真正的java中提供的链表的使用


// 引入 LinkedList 类
import java.util.LinkedList; 

LinkedList<E> list = new LinkedList<E>();   // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
LinkedList<Integer> linkedList = new LinkedList<>();//链表的实例化
        linkedList.add(1);
        linkedList.add(2);
        linkedList.add(3);
        linkedList.add(4);
        linkedList.add(5);
        linkedList.add(6);
        linkedList.add(7);
        //foreach遍历
        for (int e:
             linkedList) {
            System.out.println(e);
        }
        //迭代器正向遍历
        ListIterator<Integer> iterator = linkedList.listIterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next() + " ");
        }
        //反向迭代器反向遍历
        while (iterator.hasPrevious()){
            System.out.println(iterator.previous() + " ");
        }

关于双向链表的例题很多都要涉及后面诸如栈队列的内容,所以先不提供了,同时我们也可以发现,同样的题,双向链表要比单向链表要容易解决,因为它可以记录前后两个节点。

总结

本篇文章介绍了有关数据结构中链表的相关内容,如单向链表,双向链表,如果有什么不正确的、不严谨的地方,还望指正,谢谢大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2239180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

typesScript 制作一个简易的区块链(2)

pow 机制 1.哈希函数的特点 说到 pow 机制&#xff0c;就离不开哈希函数&#xff0c;哈希函数具有以下特点&#xff1a; 输入长度不固定&#xff0c;输出长度固定输入不同&#xff0c;输出不同输入相同&#xff0c;输出相同不可逆雪崩效应 雪崩效应&#xff1a;输入变量中只…

[Codesys]常用功能块应用分享-BMOV功能块功能介绍及其使用实例说明

官方说明 功能说明 参数 类型 功能 pbyDataSrcPOINTER TO BYTE指向源数组指针uiSizeUINT要移动数据的BYTE数pbyDataDesPOINTER TO BYTE指向目标数组指针 实例应用-ST IF SYSTEM_CLOCK.AlwaysTrue THENCASE iAutoState OF0: //读写完成信号在下次读写信号的上升沿或复位信号…

【树莓派raspberrypi烧录Ubuntu远程桌面登入树莓派】

提示&#xff1a;本文利用的是Ubuntu主机和树莓派4B开发板&#xff0c;示例仅供参考 文章目录 一、树莓派系统安装下载前准备工作下载安装树莓派的官方烧录软件imagerimager的使用方法 二、主机与树莓SSH连接查看数梅派IP地址建立ssh连接更新树莓派源地址 三、主机端远程桌面配…

Linux权限和开发工具(3)

文章目录 1. 简单理解版本控制器Git1. 如何理解版本控制 2. Git的操作2.1 Git安装2.2 Git提交身份2.3 Git提交命令2.4 Git版本管理2.5 Git下的同步 3. gdb命令3.1解决gdb的难用问题3.2 gdb/cgdb的使用 1. 简单理解版本控制器Git 1. 如何理解版本控制 我们在做项目的时候可能会…

如何在 Django 中生成 Excel 文件并上传至 FastDFS

文章目录 如何在 Django 中生成 Excel 文件并上传至 FastDFS需求背景主要任务 实现步骤 创建 Excel 文件上传 Excel 文件到 FastDFSclient.conf 保存文件 URL 到数据库组合完整的流程总结 如何在 Django 中生成 Excel 文件并上传至 FastDFS 在很多实际应用场景中&#xff0c;我…

电子应用产品设计方案-3:插座式自动温控器设计

一、设计 插座式自动温控器作为一种便捷的温度控制设备&#xff0c;在日常生活和工业应用中发挥着重要作用。它能够根据环境温度的变化自动控制连接设备的电源通断&#xff0c;实现对温度的精确调节和节能控制。本设计旨在提供一种功能强大、易于使用、安全可靠的插座式自动温控…

Redis的常用命令大全

目录 一、Redis简介 1.键值型 2.NoSQL 2.1关联和非关联 2.2查询方式 2.3事务 2.4总结 二、Redis常见命令 2.1 通用命令 2.2 String 命令 2.3 Hash类型 2.4 List类 2.5 Set集合 2.6 SortedSet类型 一、Redis简介 Redis是一种键值型的NoSql数据库&#xff0c;这里…

浅谈PostGIS中的抽稀技术——实现高效空间数据可视化的关键

目录 前言 一、原始数据介绍 1、原始完整数据 2、Qgis中展示原始数据 二、减少数据精度 1、查询函数简介 2、减少精度实战 三、ST_Simplify抽稀实现 1、ST_Simplify函数介绍 2、ST_Simplify抽稀结果 四、ST_SimplifyPreserveTopology抽稀 1、函数介绍 2、抽稀结果 …

网约车管理:规范发展,保障安全与便捷

在数字化时代&#xff0c;网约车已成为城市出行的重要组成部分&#xff0c;为公众提供了前所未有的便捷性。然而&#xff0c;随着网约车行业的迅猛发展&#xff0c;一系列管理问题也随之浮现&#xff0c;如司机资质审核不严、车辆安全标准不一、乘客权益保护不足等。这些问题不…

vue3入门和实战-vue3项目布局

文章目录 前言一、项目目标二、页面布局1.首页布局分析2. 首页布局实现App.vueLayoutIndex.vueLayoutLeft.vueHome.vueHome/components/Header.vueHome/components/Footer.vue3.首页路由4.首页效果显示总结前言 上一节,部署了vue3官方案例,我们需要结合自身项目页面的布局改…

深度学习经典模型之VGGNet

1 VGGNet 1.1 模型介绍 ​ VGGNet是由牛津大学视觉几何小组&#xff08;Visual Geometry Group, VGG&#xff09;提出的一种深层卷积网络结构&#xff0c;他们以7.32%的错误率赢得了2014年ILSVRC分类任务的亚军&#xff08;冠军由GoogLeNet以6.65%的错误率夺得&#xff09;和…

【364】基于springboot的高校科研信息管理系统

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

【Windows】CMD命令学习——系统命令

CMD&#xff08;命令提示符&#xff09;是Windows操作系统中的一个命令行解释器&#xff0c;允许用户通过输入命令来执行各种系统操作。 系统命令 systeminfo - 显示计算机的详细配置信息。 tasklist - 显示当前正在运行的进程列表。 taskkill - 终止正在运行的进程。例如&am…

深入探索Waymo自动驾驶技术发展:从DARPA挑战赛到第五代系统的突破

引言 自动驾驶技术正引领着未来出行方式的革命&#xff0c;而Waymo作为全球自动驾驶领域的先锋&#xff0c;始终走在技术发展的最前沿。本文基于Waymo联席CEO德米特里多尔戈夫&#xff08;Dmitri Dolgov&#xff09;在No Priors节目中的访谈&#xff0c;全面介绍Waymo的技术发展…

泷羽sec学习打卡-Windows基础virus

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于windows virus的那些事儿 一、Windows-Virus资源耗尽之无限弹窗cmd-virus测试锁机virus测试无限重启…

python机器人Agent编程——实现一个本地大模型和爬虫结合的手机号归属地天气查询Agent

目录 一、前言二、准备工作三、Agent结构四、python模块实现4.1 实现手机号归属地查询工具4.2实现天气查询工具4.3定义创建Agent主体4.4创建聊天界面 五、小结PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源ps3.移动小车相关文章资源ps3.wifi小车控制相关…

如何线程安全的使用HashMap

前言 Map一直是面试中经常被问到的问题。博主在找工作的过程中&#xff0c;就被问到了这样一个问题&#xff1a; Map是线程安全的吗&#xff1f;我不考虑使用线程安全的Map(eg&#xff1a;ConcurrentHashMap) 。如何在多线程/高并发下安全使用 HashMap&#xff1f; 当时博主…

基于MATLAB+opencv人脸疲劳检测

我们可以通过多种方式从现实世界中获取数字图像&#xff0c;比如&#xff1a;数码相机、扫描仪、计算机扫描和磁共振成像等等。在这些情况中&#xff0c;虽然我们肉眼看到的是图像&#xff0c;但是当需要将图像在数字设备中变换传输时&#xff0c;图像的每个像素则对应一个数值…

区块链技术在知识产权保护中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在知识产权保护中的应用 区块链技术在知识产权保护中的应用 区块链技术在知识产权保护中的应用 引言 区块链技术概述 …

交友系统app源码优势,怎么去开发一个交友系统,它适合的场景

https://gitee.com/fantnerd/hunlian.githttps://gitee.com/fantnerd/hunlian.git 语音交友app源码技术优势&#xff1a; 1、语音交友app源码服务端开发语言采用PHP。 2、服务端开发框架主要TP6 3、开发环境&#xff1a;Nginx或者Apache 数据库mysql5.6。 交友程序源码的开发…