数据结构——(双)链表

文章目录

1. 定义

2. 双链表和单链表的区别

3. 代码示例

3.1 双链表节点和结构定义

3.2 初始化双链表

3.3 返回双链表的长度

3.4 在指定位置插入元素

3.5 在末尾插入元素

3.6 删除指定位置的元素并返回被删除的元素

3.7 删除末尾元素

3.8 获取指定位置的元素

3.9 修改指定位置的元素

3.10 释放双链表内存

4. 流程

5. 完整代码


1. 定义

双链表(Doubly Linked List)是一种链表数据结构,其中每个节点不仅包含一个数据域,还包含两个指针域,一个指向前驱节点,一个指向后继节点。相比单链表,双链表可以更方便地进行双向遍历,插入和删除操作也更高效。

双链表的定义和操作

  1. 节点的定义:每个节点包含数据部分和指向前一个节点和后一个节点的指针部分。
  2. 头节点和尾节点:链表的头节点是链表的起点,尾节点是链表的终点,通过头节点可以遍历整个链表。
  3. 双向链接:每个节点都有指向前一个节点和后一个节点的指针,因此可以双向遍历链表。
  4. 动态扩展:节点在内存中不必是连续的,可以动态分配和释放内存。

2. 双链表和单链表的区别

结构上的区别

  • 单链表

    • 每个节点包含一个数据域和一个指向下一个节点的指针。
    • 只有从头节点向下遍历的方向,没有指向前一个节点的指针。
    • 头节点没有前驱节点,尾节点的指针指向 NULL
  • 双链表

    • 每个节点包含一个数据域、一个指向下一个节点的指针和一个指向前一个节点的指针。
    • 可以从任一节点双向遍历,即可以向前遍历到头节点,也可以向后遍历到尾节点。
    • 头节点的前驱指针指向 NULL,尾节点的后继指针指向 NULL

单链表的优缺点

优点

  1. 简单性:实现和维护相对简单,节点只需要存储一个指针,内存开销小。
  2. 内存占用较少:每个节点只包含一个指针,因此内存占用较双链表少。
  3. 插入和删除操作效率较高:在已知前驱节点的情况下,插入和删除节点的时间复杂度为 O(1)。

缺点

  1. 查找效率较低:从头节点遍历到目标节点的时间复杂度为 O(n)。
  2. 只能单向遍历:不能从尾节点向前遍历到头节点,灵活性差。

双链表的优缺点

优点

  1. 双向遍历:可以从任一节点双向遍历,即可以向前遍历到头节点,也可以向后遍历到尾节点。
  2. 删除节点更方便:在已知节点本身的情况下,删除节点时不需要知道其前驱节点,因为可以通过节点本身直接访问其前驱节点和后继节点。
  3. 灵活性高:在某些情况下,双向遍历能够更方便地实现算法,比如在某些需要回溯的场景下。

缺点

  1. 内存占用较大:每个节点包含两个指针,内存占用较单链表多。
  2. 实现和维护相对复杂:双向链表的实现和维护比单链表更复杂,需要处理更多的指针操作。
  3. 插入和删除操作相对复杂:插入和删除操作需要同时更新前驱和后继节点的指针,操作较为繁琐。

3. 代码示例

3.1 双链表节点和结构定义

#include <stdio.h>
#include <stdlib.h>// 双链表节点结构定义
typedef struct DNode {int data;             // 节点存储的数据struct DNode *prev;   // 指向前一个节点的指针struct DNode *next;   // 指向后一个节点的指针
} DNode;// 双链表结构定义
typedef struct {DNode *head;  // 双链表头节点指针DNode *tail;  // 双链表尾节点指针size_t size;  // 双链表中的节点个数
} DoublyLinkedList;
  • DNode 结构体定义了双链表的节点,包含数据域 data 和指向前一个节点的指针 prev 以及指向后一个节点的指针 next
  • DoublyLinkedList 结构体定义了双链表,包含指向头节点的指针 head 和指向尾节点的指针 tail,以及链表中节点的个数 size

3.2 初始化双链表

// 初始化双链表
void initDoublyLinkedList(DoublyLinkedList *list) {list->head = NULL; // 初始化头节点为空list->tail = NULL; // 初始化尾节点为空list->size = 0;    // 初始化节点个数为0
}

  • initDoublyLinkedList 函数将双链表的头节点和尾节点设置为 NULL,并将节点个数初始化为 0。

3.3 返回双链表的长度

// 返回双链表的长度
size_t getLength(const DoublyLinkedList *list) {return list->size; // 返回双链表的节点个数
}
  •  getLength 函数返回双链表中的节点个数。

3.4 在指定位置插入元素

// 在指定位置插入元素
void insertAt(DoublyLinkedList *list, size_t index, int element) {// 检查插入位置是否有效if (index > list->size) {return; // 忽略无效的插入位置}// 创建新节点DNode *newNode = (DNode *)malloc(sizeof(DNode));newNode->data = element;newNode->prev = NULL;newNode->next = NULL;// 如果插入位置是头节点if (index == 0) {newNode->next = list->head;if (list->head != NULL) {list->head->prev = newNode;}list->head = newNode; // 新节点成为头节点if (list->tail == NULL) {list->tail = newNode; // 如果链表为空,新节点也是尾节点}} else if (index == list->size) {// 如果插入位置是尾节点newNode->prev = list->tail;if (list->tail != NULL) {list->tail->next = newNode;}list->tail = newNode; // 新节点成为尾节点if (list->head == NULL) {list->head = newNode; // 如果链表为空,新节点也是头节点}} else {// 找到插入位置的前一个节点DNode *current = list->head;for (size_t i = 0; i < index - 1; i++) {current = current->next;}// 插入新节点newNode->next = current->next;newNode->prev = current;if (current->next != NULL) {current->next->prev = newNode;}current->next = newNode;}list->size++; // 更新节点个数
}
  • insertAt 函数在双链表的指定位置插入一个新的元素。如果插入位置是 0,则新节点成为头节点。如果插入位置是链表的末尾,则新节点成为尾节点。否则,通过遍历找到插入位置的前一个节点,并在该位置插入新节点。更新链表的节点个数。

3.5 在末尾插入元素

// 在末尾插入元素
void insertEnd(DoublyLinkedList *list, int element) {insertAt(list, list->size, element); // 在链表末尾插入元素
}
  • insertEnd 函数在双链表末尾插入一个新的元素,通过调用 insertAt 函数实现。

3.6 删除指定位置的元素并返回被删除的元素

// 删除指定位置的元素并返回被删除的元素
int deleteAt(DoublyLinkedList *list, size_t index) {// 检查删除位置是否有效if (index >= list->size) {return -1; // 忽略无效的删除位置}int deletedElement;// 如果删除位置是头节点if (index == 0) {DNode *temp = list->head;list->head = temp->next;if (list->head != NULL) {list->head->prev = NULL;} else {list->tail = NULL; // 如果链表只有一个节点}deletedElement = temp->data;free(temp); // 释放被删除节点的内存} else if (index == list->size - 1) {// 如果删除位置是尾节点DNode *temp = list->tail;list->tail = temp->prev;if (list->tail != NULL) {list->tail->next = NULL;} else {list->head = NULL; // 如果链表只有一个节点}deletedElement = temp->data;free(temp); // 释放被删除节点的内存} else {// 找到删除位置的前一个节点DNode *current = list->head;for (size_t i = 0; i < index - 1; i++) {current = current->next;}// 删除节点DNode *temp = current->next;current->next = temp->next;if (temp->next != NULL) {temp->next->prev = current;}deletedElement = temp->data;free(temp); // 释放被删除节点的内存}list->size--; // 更新节点个数return deletedElement;
}
  • deleteAt 函数删除双链表中指定位置的节点,并返回该节点的值。如果删除位置是 0,则直接删除头节点。如果删除位置是链表的末尾,则删除尾节点。否则,通过遍历找到删除位置的前一个节点,并删除该位置的节点。更新链表的节点个数。

3.7 删除末尾元素

// 删除末尾元素并返回被删除的元素
int deleteEnd(DoublyLinkedList *list) {return deleteAt(list, list->size - 1); // 删除链表末尾的元素
}
  • deleteEnd 函数删除双链表末尾的节点,通过调用 deleteAt 函数实现。

3.8 获取指定位置的元素

// 获取指定位置的元素
int getElementAt(const DoublyLinkedList *list, size_t index) {// 检查索引位置是否有效if (index >= list->size) {return -1; // 返回无效的索引}// 遍历找到指定位置的节点DNode *currentNode = list->head;for (size_t i = 0; i < index; i++) {currentNode = currentNode->next;}return currentNode->data; // 返回指定位置的元素
}
  • getElementAt 函数返回双链表中指定位置的元素。通过遍历找到指定位置的节点,并返回该节点的值。

3.9 修改指定位置的元素

// 修改指定位置的元素
void modifyAt(DoublyLinkedList *list, size_t index, int newValue) {// 检查修改位置是否有效if (index >= list->size) {return; // 忽略无效的修改位置}// 遍历找到指定位置的节点DNode *currentNode = list->head;for (size_t i = 0; i < index; i++) {currentNode = currentNode->next;}currentNode->data = newValue; // 修改节点的值
}
  • modifyAt 函数修改双链表中指定位置的元素值。通过遍历找到指定位置的节点,并修改该节点的值。

3.10 释放双链表内存

// 释放双链表内存
void destroyDoublyLinkedList(DoublyLinkedList *list) {// 遍历释放每个节点的内存DNode *currentNode = list->head;while (currentNode != NULL) {DNode *temp = currentNode;currentNode = currentNode->next;free(temp); // 释放每个节点的内存}list->head = NULL; // 头节点置为空list->tail = NULL; // 尾节点置为空list->size = 0;    // 节点个数置为0
}
  • destroyDoublyLinkedList 函数释放双链表使用的内存。通过遍历链表,逐个释放每个节点的内存。将头节点和尾节点指针置为空,节点个数置为 0。

4. 流程

初始化双链表

  • 判断链表是否为空。
  • 如果为空,设置头指针和尾指针为NULL。
  • 如果不为空,创建头节点和尾节点。

插入节点

  • 判断插入位置是在头部、尾部还是中间。
  • 如果是头部,设置新节点为头节点并更新头节点的前驱指针。
  • 如果是尾部,设置新节点为尾节点并更新尾节点的后继指针。
  • 如果是在中间,找到插入位置前一个节点,设置新节点的前驱和后继指针,并更新前一个节点和后一个节点的指针。
  • 更新链表长度。

删除节点

  • 判断删除位置是在头部、尾部还是中间。
  • 如果是头部,找到头节点并更新头节点指针。
  • 如果是尾部,找到尾节点并更新尾节点指针。
  • 如果是在中间,找到要删除节点的前一个节点,更新前一个节点和后一个节点的指针。
  • 释放被删除节点的内存。
  • 更新链表长度。

遍历链表

  • 从头节点开始。
  • 判断当前节点是否为NULL。
  • 如果不为NULL,访问节点数据并移动到下一个节点,重复判断。
  • 如果为NULL,遍历结束。

修改节点数据

  • 找到目标节点。
  • 更新节点数据。

 

5. 完整代码

代码包括双链表的基本操作,包括初始化、插入、删除、获取和修改元素,以及释放链表的内存.

#include <stdio.h>
#include <stdlib.h>// 双链表节点结构定义
typedef struct DNode {int data;           // 节点存储的数据struct DNode *prev; // 指向前一个节点的指针struct DNode *next; // 指向后一个节点的指针
} DNode;// 双链表结构定义
typedef struct {DNode *head; // 双链表头节点指针DNode *tail; // 双链表尾节点指针size_t size; // 双链表中的节点个数
} DoublyLinkedList;// 初始化双链表
void initDoublyLinkedList(DoublyLinkedList *list) {list->head = NULL; // 初始化头节点为空list->tail = NULL; // 初始化尾节点为空list->size = 0;    // 初始化节点个数为0
}// 返回双链表的长度
size_t getLength(const DoublyLinkedList *list) {return list->size; // 返回双链表的节点个数
}// 在指定位置插入元素
void insertAt(DoublyLinkedList *list, size_t index, int element) {if (index > list->size) {return; // 忽略无效的插入位置}DNode *newNode = (DNode *)malloc(sizeof(DNode)); // 创建新节点newNode->data = element;newNode->prev = NULL;newNode->next = NULL;if (index == 0) { // 插入位置是头节点newNode->next = list->head;if (list->head != NULL) {list->head->prev = newNode;}list->head = newNode;if (list->tail == NULL) {list->tail = newNode;}} else if (index == list->size) { // 插入位置是尾节点newNode->prev = list->tail;if (list->tail != NULL) {list->tail->next = newNode;}list->tail = newNode;if (list->head == NULL) {list->head = newNode;}} else {DNode *current = list->head;for (size_t i = 0; i < index - 1; i++) {current = current->next;}newNode->next = current->next;newNode->prev = current;if (current->next != NULL) {current->next->prev = newNode;}current->next = newNode;}list->size++; // 更新节点个数
}// 在末尾插入元素
void insertEnd(DoublyLinkedList *list, int element) {insertAt(list, list->size, element); // 在链表末尾插入元素
}// 删除指定位置的元素并返回被删除的元素
int deleteAt(DoublyLinkedList *list, size_t index) {if (index >= list->size) {return -1; // 忽略无效的删除位置}int deletedElement;if (index == 0) { // 删除位置是头节点DNode *temp = list->head;list->head = temp->next;if (list->head != NULL) {list->head->prev = NULL;} else {list->tail = NULL; // 如果链表只有一个节点}deletedElement = temp->data;free(temp); // 释放被删除节点的内存} else if (index == list->size - 1) { // 删除位置是尾节点DNode *temp = list->tail;list->tail = temp->prev;if (list->tail != NULL) {list->tail->next = NULL;} else {list->head = NULL; // 如果链表只有一个节点}deletedElement = temp->data;free(temp); // 释放被删除节点的内存} else {DNode *current = list->head;for (size_t i = 0; i < index - 1; i++) {current = current->next;}DNode *temp = current->next;current->next = temp->next;if (temp->next != NULL) {temp->next->prev = current;}deletedElement = temp->data;free(temp); // 释放被删除节点的内存}list->size--; // 更新节点个数return deletedElement;
}// 删除末尾元素并返回被删除的元素
int deleteEnd(DoublyLinkedList *list) {return deleteAt(list, list->size - 1); // 删除链表末尾的元素
}// 获取指定位置的元素
int getElementAt(const DoublyLinkedList *list, size_t index) {if (index >= list->size) {return -1; // 返回无效的索引}DNode *currentNode = list->head;for (size_t i = 0; i < index; i++) {currentNode = currentNode->next;}return currentNode->data; // 返回指定位置的元素
}// 修改指定位置的元素
void modifyAt(DoublyLinkedList *list, size_t index, int newValue) {if (index >= list->size) {return; // 忽略无效的修改位置}DNode *currentNode = list->head;for (size_t i = 0; i < index; i++) {currentNode = currentNode->next;}currentNode->data = newValue; // 修改节点的值
}// 释放双链表内存
void destroyDoublyLinkedList(DoublyLinkedList *list) {DNode *currentNode = list->head;while (currentNode != NULL) {DNode *temp = currentNode;currentNode = currentNode->next;free(temp); // 释放每个节点的内存}list->head = NULL; // 头节点置为空list->tail = NULL; // 尾节点置为空list->size = 0;    // 节点个数置为0
}// 打印双链表中的所有元素
void printDoublyLinkedList(const DoublyLinkedList *list) {DNode *currentNode = list->head;while (currentNode != NULL) {printf("%d ", currentNode->data);currentNode = currentNode->next;}printf("\n");
}// 主函数测试双链表操作
int main() {DoublyLinkedList myList; // 声明双链表initDoublyLinkedList(&myList); // 初始化双链表printf("初始化双链表成功!\n");insertEnd(&myList, 1); // 链表尾部插入元素1insertEnd(&myList, 2); // 链表尾部插入元素2insertEnd(&myList, 3); // 链表尾部插入元素3printf("向双链表插入了3个元素\n");printDoublyLinkedList(&myList); // 打印链表中的元素printf("双链表长度为: %zu\n", getLength(&myList)); // 获取双链表长度insertAt(&myList, 1, 4); // 在索引1处插入元素4printf("在索引1处插入元素4\n");printDoublyLinkedList(&myList); // 打印链表中的元素printf("双链表长度为: %zu\n", getLength(&myList)); // 再次获取双链表长度printf("索引1处的元素为: %d\n", getElementAt(&myList, 1)); // 获取索引1处的元素modifyAt(&myList, 0, 5); // 修改索引0处的元素printf("把索引0处的元素修改为5\n");printDoublyLinkedList(&myList); // 打印链表中的元素printf("删除索引1处的元素,该元素值是: %d\n", deleteAt(&myList, 1)); // 删除索引1处的元素printDoublyLinkedList(&myList); // 打印链表中的元素destroyDoublyLinkedList(&myList); // 销毁双链表printf("双链表销毁成功!\n");return 0;
}
  • 初始化双链表initDoublyLinkedList 函数初始化双链表,将头节点和尾节点设置为 NULL,节点个数初始化为 0。
  • 返回双链表的长度getLength 函数返回双链表中的节点个数。
  • 在指定位置插入元素insertAt 函数在双链表的指定位置插入一个新节点,根据插入位置调整前后节点的指针。
  • 在末尾插入元素insertEnd 函数在双链表末尾插入一个新节点,调用 insertAt 函数实现。
  • 删除指定位置的元素deleteAt 函数删除双链表中指定位置的节点,并返回该节点的值,根据删除位置调整前后节点的指针。
  • 删除末尾元素deleteEnd 函数删除双链表末尾的节点,调用 deleteAt 函数实现。
  • 获取指定位置的元素getElementAt 函数返回双链表中指定位置的元素,通过遍历找到目标节点。
  • 修改指定位置的元素modifyAt 函数修改双链表中指定位置的节点的值,通过遍历找到目标节点并更新其数据。
  • 释放双链表内存destroyDoublyLinkedList 函数释放双链表中的所有节点内存,并将链表恢复到初始状态。
  • 打印双链表中的所有元素printDoublyLinkedList 函数遍历双链表并打印每个节点的数据。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

maven项目使用netty,前端是vue2,实现通讯

引入的java包 <!-- 以下是即时通讯--><!-- Netty core modules --><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.76.Final</version> <!-- 使用最新的稳定版本…

Docker:三、安装nginx与tomcat

&#x1f341;安装常见服务 &#x1f332;安装nginx &#x1f9ca;1、搜索镜像 Ⅰ.hub docker上查询&#xff1a;https://hub.docker.com/_/nginx Ⅱ. 命令查询&#xff1a;docker search nginx &#x1f9ca;2、下载镜像 命令&#xff1a;docker pull nginx &#x1f9c…

应用了网络变压器的PC网卡连接转换器后不好连网,有掉线现象,但外接路由器无问题,可能是什么原因?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是应用了网络变压器的PC网卡连接转换器后不好连网&#xff0c;有掉线现象&#xff0c;但外接路由器无问题&#xff0c;可能是什么原因呢&#xff1f;如何解决呢&#xff1f; 首先&#xff0c;我们要了解传…

PMP–知识卡片--PDCA循环

记忆 PDCA&#xff1a;计划执行检查调整&#xff0c;计划观察动作&#xff1b;plan do check action 定义 PDCA循环的含义是将质量管理分为四个过程&#xff0c;即计划&#xff08;Plan&#xff09;、执行&#xff08;Do&#xff09;、检查&#xff08;Check&#xff09;、处…

使用maven搭建一个SpingBoot项目

1.首先创建一个maven项目 注意选择合适的jdk版本 2.添加依赖 2.在pom.xml中至少添加依赖 spring-boot-starter-web 依赖&#xff0c;目的是引入Tomcat&#xff0c;以及SpringMVC等&#xff0c;使项目具有web功能。 <!-- 引入 包含tomcat&#xff0c;SpringMVC&#xff0c…

一文了解常见DNS问题

当企业的DNS出现故障时&#xff0c;为不影响企业的正常运行&#xff0c;团队需要能够快速确定问题的性质和范围。那么有哪些常见的DNS问题呢&#xff1f; 域名解析失败&#xff1a; 当您输入一个域名&#xff0c;但无法获取到与之对应的IP地址&#xff0c;导致无法访问相应的网…

HTTP代理服务器:深度解析与应用

“随着互联网的飞速发展&#xff0c;HTTP代理服务器在网络通信中扮演着越来越重要的角色。它们作为客户端和服务器之间的中介&#xff0c;不仅优化了网络性能&#xff0c;还提供了强大的安全性和隐私保护功能。” 一、HTTP代理服务器的概念与作用 HTTP代理服务器是一种能够接…

win11如何关闭自动更新,延长暂停更新时间

网上有很多关闭自动更新的方法&#xff0c;今天给大家带来另一种关闭win11自动更新的方法。 1.winR打开运行窗口&#xff0c;输入regedit打开注册表 2.定位到以下位置&#xff1a; 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 3.右键右边空白&…

实验四 图像增强—灰度变换之直方图变换

一&#xff0e;实验目的 1&#xff0e;掌握灰度直方图的概念及其计算方法&#xff1b; 2&#xff0e;熟练掌握直方图均衡化计算过程&#xff1b;了解直方图规定化的计算过程&#xff1b; 3&#xff0e;了解色彩直方图的概念和计算方法 二&#xff0e;实验内容&#xff1a; …

jenkins搭建部署前端工程 ,从0到1

一.java环境配置 1 安装tomcatjdk17 这个也行 3 安装maven3.3.9 安装教程参考 4 安装Jenkins 下载地址 参考教程 二、相关配置 1 访问http://localhost:8080/jenkins&#xff0c;进入Jenkins初始化页面&#xff0c;第一次启动时间可能有点长&#xff0c;耐心等待。进入成功后会…

vue3自定义全局指令和局部指令

1.全局指令 el&#xff1a;指令绑定到的DOM元素&#xff0c;可以用于直接操作当前元素&#xff0c;默认传入钩子的就是el参数&#xff0c;例如我们开始实现的focus指令&#xff0c;就是直接操作的元素DOM binding&#xff1a;这是一个对象&#xff0c;包含以下属性&#xff1a;…

2.5 C#视觉程序开发实例1----IO_Manager实现切换程序

2.5 C#视觉程序开发实例1----IO_Manager实现切换程序 1 IO_Manager中输入实现 1.0 IO_Manager中输入部分引脚定义 // 设定index 目的是为了今后可以配置这些参数、 // 输入引脚定义 private int index_trig0 0; // trig index private int index_cst 7; //cst index priva…

element-ui Tree之懒加载叶子节点强制设置父级半选效果

效果&#xff1a; 前言&#xff1a; 我们是先只展示一级的&#xff0c;二级的数据是通过点击之后通过服务器获取数据&#xff0c;并不是全量数据直接一起返回回来的。 问题&#xff1a; 当你设置了默认选中的子节点&#xff0c;但是由于刚进入页面此时tree中数据暂是没有这个…

【C++题解】1561. 买木头

问题&#xff1a;1561. 买木头 类型&#xff1a;省赛、数组问题、二分答案、贪心、2015江苏省青少年信息学奥林匹克竞赛复赛 题目描述&#xff1a; 有 n 个木材供应商&#xff0c;每个供货商有长度相同一定数量的木头。长木头可以锯短&#xff0c;但短木头不能接长。有一个客…

解决obsidian加粗中文字体显示不突出的问题

加粗字体显示不突出的原因&#xff1a;默认字体的加粗版本本来就不突出 解决方法&#xff1a;改成显示突出的类型Microsoft YaHei UI 【效果】 修改前&#xff1a;修改后&#xff1a; 其他方法&#xff1a; 修改css&#xff08;很麻烦&#xff0c;改半天也不一定奏效&#…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】认证服务03—分布式下Session共享问题

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】分布式下Session共享问题 session原理分布式下session共享问题Session共享问题解决—session复制Session共享问题解决—客户端存储Session共享问题解决—hash一致性Session共享问题…

使用 OpenCV 和 Python 进行车道检测和物体检测(YOLO)

本项目旨在开发一个集车道检测与物体检测功能于一体的智能视觉分析系统&#xff0c;利用先进的计算机视觉技术和深度学习模型&#xff0c;实现实时的道路场景理解和目标识别。系统主要依托OpenCV这一强大的计算机视觉库&#xff0c;以及Python作为编程语言&#xff0c;融合了车…

Golang | Leetcode Golang题解之第206题反转链表

题目&#xff1a; 题解&#xff1a; func reverseList(head *ListNode) *ListNode {if head nil || head.Next nil {return head}newHead : reverseList(head.Next)head.Next.Next headhead.Next nilreturn newHead }

24西安电子科技大学马克思主义学院—考研录取情况

01、马克思主义学院各个方向 02、24马克思主义学院近三年复试分数线对比 PS&#xff1a;马院24年院线相对于23年院线增加15分&#xff0c;反映了大家对于马克思主义理论学习与研究的热情高涨&#xff0c;也彰显了学院在人才培养、学科建设及学术研究等方面的不断进步与成就。 6…

UE4_材质_材质节点_Fresnel

学习笔记&#xff0c;不喜勿喷&#xff0c;侵权立删&#xff0c;祝愿生活越来越好&#xff01; 一、问题导入 在创建电影或过场动画时&#xff0c;你常常需要想办法更好地突显角色或场景的轮廓。这时你需要用到一种光照技术&#xff0c;称为边沿光照或边缘光照&#xff0c;它的…