数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看

前言

  • 这个专栏将会用纯C实现常用的数据结构和简单的算法;
  • C基础即可跟着学习,代码均可运行;
  • 准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言实现的原因之一
  • 欢迎收藏 + 关注,本人将会持续更新。

文章目录

  • :man_teacher:单链表讲解
  • :information_desk_person:单链表程序设计
    • 有头单链表
    • 无头单链表
      • 再封装写法
      • 二级指针写法
  • :man_factory_worker:单链表的一些操作
    • 有序链表的构建
    • 排序链表
    • 链表反转

👨‍🏫单链表讲解

上一节我们学习了顺序表,顺序表是运用最多的和最简单的顺序存储结构,但是顺序表的删除很麻烦,顺序表的删除是一种伪删除,他删除元素是通过后面元素覆盖而来,假设要删除的元素在第一位,那么他的时间复杂度是O(n),而且他并没有释放那个内存,故如果我们的运用场景是需要有经常删除的需求,那这个顺序表就并不适合🙉🙉🙉,插入操作也同样的道理

为了避免插入和删除的线性开销,研究数据结构的数学家就设计出了链式存储结构来存储数据,它允许表 可以不连续存储,在插入和删除的时候不需要整体移动,链式存储的存储结构如下图所示:

在这里插入图片描述

链表由一系列不必存在内存中连续的空间的结构组成;每一个结构都有包含元素的数据域和指向下一个节点的指针域,指针域存储指向下一个节点的指针,最后一个元素的指针指向为NULL


在这里我们首先回忆以下指针变量,指针他本身是一个变量,他储存的是一个变量的地址,故联系到我们这一部分的链表,假设我们有一个指向节点P的变量,那么就可以通过P->next指针来寻找下一个节点的位置,如下图所示:

在这里插入图片描述


链表之所以可以解决顺序表的删除和插入效率的问题,因为他每一个节点都储存了指向下一个元素的指针,所以,它可以通过修改指针的指向实现删除的命令,大概流程如下:

在这里插入图片描述

同样的道理,插入元素也是这样,当我们使用内存申请函数开辟了一篇内存后,通过修改指针的指向即可实现插入,大概流程如图:

在这里插入图片描述

💁单链表程序设计

📂 链表的操作,总的来说还在那句话:增删改查

🕵 程序设计细节:

  1. 插入元素中,空表插入、头插、位置插入不同;
  2. 删除头的时候,由于修改了起始端,故要注意表头丢失的问题;
  3. 一般删除的时候,需要记录要删除位置的前一个位置节点的表元。

🔬 解决方法:

  1. 实际操作的时候分类讨论;
  2. 采用添加头节点的方法来解决,添加的节点称为表头或者哑节点,这种链表称为有头链表

有头单链表

有头链表结构图如下:
在这里插入图片描述

通过引入头节点,其实主要解决了插入的时候指针的指向问题与插入过程会简单一点。

想要理解这个,最直观的方法就是通过学习有头链表和无头链表的代码实现过程.


节点封装

typedef int DataType;
typedef struct Node {DataType data;   // 数据域,储存数据struct Node* next;  // 指针域,储存指向下一个节点的指针
}Node;

🍨 创建节点

采用内存申请的函数,申请一块内存来储存节点。

🤔 思考:如果使用malloc去申请内存,那有什么区别呢????????????

// 创建节点
Node* create_node(DataType data)
{Node* node = calloc(1, sizeof(Node));assert(node);node->data = data;return node;
}

⚜️ 创建链表

🤕 这一步就是创建了一块表头,也可以说叫做虚拟头节点、哑节点,里面储存的是什么数据,我们不需要担心。

Node* create_list()
{Node* list = calloc(1, sizeof(Node));assert(list);return list;
}

🤕 插入元素–头插

头插过程:

cc在这里插入图片描述

📘 情况:

  1. 没有头;
  2. 有头,则在头前面插入。
void push_front(Node* head, DataType data)
{if (NULL == head) return;// 头为空if (head->next == NULL) {Node* new_node = create_node(data);head->next = new_node;}else {  // 头不为空Node* cur = head->next;  // 取头Node* new_node = create_node(data);new_node->next = cur;head->next = new_node;}
}

🌮 插入–尾插

在这里插入图片描述

void push_back(Node* head, DataType data)
{assert(head);// 空if (head->next == NULL) {Node* new_node = create_node(data);head->next = new_node;}else {  // 不为空Node* cur = head->next;  // 获取头// 找到尾while (cur->next) {cur = cur->next;}cur->next = create_node(data);}}

🗡指定位置插入

说明,以下说明完全是自己个人定义,学习思想为主,具体需要结合业务:

  • 1、pos从1开始
  • 2、在pos后面位置插入
  • 3、如何位置超出了链表长度,则当作尾插

在这里插入图片描述

void insert(Node* head, int pos, DataType data)
{assert(head);Node* cur = head->next;while (cur->next != NULL && pos > 1) {  // pos > 1,不是 pos > 0cur = cur->next;pos--;}Node* node = create_node(data);node->next = cur->next;cur->next = node;
}

🍯 删除–删除头

在这里插入图片描述

// 删除
void pop_front(Node* list)
{assert(list);Node* cur = list->next;list->next = cur->next;free(cur);cur = NULL;
}

🔚 删除尾巴

思路:

  • 找到最后一个最后一个元素,并且找得到最后一个元素的前一个元素

注意

  • 要判断 只有一个节点和空链表的情况

在这里插入图片描述

void pop_back(Node* list)
{assert(list);Node* cur = list->next;Node* pre = NULL;if (cur == NULL) {printf("链表为空\n");return;}if (cur->next == NULL) {   // 只有一个节点,头删pop_front(list);return;}// 其他情况while (cur->next != NULL) {pre = cur;cur = cur->next;}pre->next = NULL;free(cur);cur = NULL;
}

🌾 指定位置删除

删除的思路大概都一样,需要找到删除元素的前一个指针,只不过需要根据场景不同来写细节。

在这里插入图片描述

/*说明,以下说明完全是自己个人定义,学习思想为主,具体需要结合业务:
* 1、pos从1开始,1代表删除第一个节点(头)
* 2、如果超出了链表的长度,则删除失败
*/
void erase(Node* list, int pos)
{assert(list);// 头删除if (1 == pos) {pop_front(list);return;}int num = 0;Node* cur = list->next;Node* pre = list;while (cur->next && pos-- > 1) {pre = cur;cur = cur->next;}if (cur->next == NULL && pos > 1) {printf("超出链表范围\n");	}else {pre->next = cur->next;free(cur);cur = NULL;}
}

📖 总代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef int DataType;typedef struct Node {DataType data;struct Node* next;
}Node;// 创建链表
Node* create_list()
{Node* list = calloc(1, sizeof(Node));assert(list);return list;
}// 创建节点
Node* create_node(DataType data)
{Node* node = calloc(1, sizeof(Node));assert(node);node->data = data;return node;
}// 插入
void push_front(Node* head, DataType data)
{if (NULL == head) return;// 头为空if (head->next == NULL) {Node* new_node = create_node(data);head->next = new_node;}else {  // 头不为空Node* cur = head->next;  // 取头Node* new_node = create_node(data);new_node->next = cur;head->next = new_node;}
}void push_back(Node* head, DataType data)
{assert(head);// 空if (head->next == NULL) {Node* new_node = create_node(data);head->next = new_node;}else {  // 不为空Node* cur = head->next;  // 获取头// 找到尾while (cur->next) {cur = cur->next;}cur->next = create_node(data);}}/*说明,以下说明完全是自己个人定义,学习思想为主,具体需要结合业务:
* 1、pos从1开始
* 2、在pos后面位置插入
* 3、如何位置超出了链表长度,则当作尾插
*/
void insert(Node* head, int pos, DataType data)
{assert(head);Node* cur = head->next;while (cur->next != NULL && pos > 1) {  // pos > 1,不是 pos > 0cur = cur->next;pos--;}Node* node = create_node(data);node->next = cur->next;cur->next = node;
}// 删除
void pop_front(Node* list)
{assert(list);Node* cur = list->next;list->next = cur->next;free(cur);cur = NULL;
}void pop_back(Node* list)
{assert(list);Node* cur = list->next;Node* pre = NULL;if (cur == NULL) {printf("链表为空\n");return;}if (cur->next == NULL) {   // 只有一个节点,头删pop_front(list);return;}// 其他情况while (cur->next != NULL) {pre = cur;cur = cur->next;}pre->next = NULL;free(cur);cur = NULL;
}/*说明,以下说明完全是自己个人定义,学习思想为主,具体需要结合业务:
* 1、pos从1开始,1代表删除第一个节点(头)
* 2、如果超出了链表的长度,则删除失败
*/
void erase(Node* list, int pos)
{assert(list);// 头删除if (1 == pos) {pop_front(list);return;}int num = 0;Node* cur = list->next;Node* pre = list;while (cur->next && pos-- > 1) {pre = cur;cur = cur->next;}if (cur->next == NULL && pos > 1) {printf("超出链表范围\n");	}else {pre->next = cur->next;free(cur);cur = NULL;}
}// 遍历
void travel(Node* head)
{assert(head);Node* cur = head->next;while (cur) {printf("%d ", cur->data);cur = cur->next;}printf("\n");
}int main()
{Node* list = create_list();push_front(list, 1);push_front(list, 2);push_front(list, 3);travel(list);push_back(list, 5);push_back(list, 6);push_back(list, 7);travel(list);insert(list, 2, 22);insert(list, 5, 55);insert(list, 20, 20);travel(list);pop_front(list);travel(list);pop_back(list);travel(list);erase(list, 5);travel(list);return 0;
}

无头单链表

在有头链表中,我们是构造了一个虚拟节点作为头,这样可以简化很多操作,那如果不用创建新头节点又该怎么写呢?这里提供两种方法,再封装写法和二级指针写法

再封装写法

🌩 : 节点封装与链表再次封装

typedef struct Node {DataType data;struct Node* next;
}Node;
// 链表再次封装
typedef struct List {Node* headNode;int count;
}List;

🍨 创建节点

Node* create_node(DataType data) 
{Node* new_node = (Node*)calloc(1, sizeof(Node));if (new_node == NULL) {return NULL;}new_node->data = data;return new_node;
}

⚜️ 创建链表

List* create_list()
{List* list = (List*)calloc(1, sizeof(List));assert(list);return list;
}

🤕 插入元素–头插

void push_front(List* list, DataType data)
{if (list == NULL) {return;}if (list->count == 0) {Node* node = create_node(data);assert(node);list->headNode = node;}else {Node* node = create_node(data);assert(node);node->next = list->headNode;list->headNode = node;}list->count++;
}

🌮 插入–尾插

void push_back(List* list, DataType data)
{if (list == NULL) {return;}if (list->count == 0) {push_front(list, data); // 相当于头插}else {Node* cur = list->headNode;while (cur->next) {cur = cur->next;}Node* node = create_node(data);assert(node);cur->next = node;}list->count++;
}

🗡指定位置插入

// 这里定义,在找到数据后位置插入
void insert(List* list, DataType posData, DataType insertData)
{if (list == NULL || list->count == 0)return;Node* cur = list->headNode;while (cur->next && cur->data != posData) {cur = cur->next;}// cur->next == null, cur->data == posdataif (cur->data != posData) {return;}else {Node* node = create_node(insertData);assert(node);node->next = cur->next;cur->next = node;}list->count++;
}

🍯 删除–删除头

void pop_front(List* list)
{if (list == NULL || list->count == 0)return;if (list->count == 1) {Node* t = list->headNode;list->headNode = NULL;free(t);t = NULL;}else {Node* t = list->headNode;list->headNode = t->next;free(t);t = NULL;}list->count--;
}

🔚 删除尾巴

void pop_back(List* list)
{if (list == NULL || list->count == 0)return;if (list->headNode->next == NULL) {free(list->headNode);list->headNode = NULL;}else {// 双指针Node* pre = list->headNode;Node* tail = list->headNode->next;while (tail->next != NULL) {pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}list->count--;
}

🌾 指定位置删除

void earse(List* list, DataType data)
{if (list == NULL || list->count == 0)return;Node* pre = NULL;Node* pos = list->headNode;// 没有到终点,且没有找到datawhile (pos != NULL && pos->data != data) {pre = pos;pos = pre->next;}if (pos == NULL) {return;}else if(pre == NULL){pop_front(list);}else {pre->next = pos->next;free(pos);pos = NULL;}list->count--;
}

⭕️ 总代码

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>typedef int DataType;typedef struct Node {DataType data;struct Node* next;
}Node;typedef struct List {Node* headNode;int count;
}List;Node* create_node(DataType data) 
{Node* new_node = (Node*)calloc(1, sizeof(Node));if (new_node == NULL) {return NULL;}new_node->data = data;return new_node;
}List* create_list()
{List* list = (List*)calloc(1, sizeof(List));assert(list);return list;
}void push_front(List* list, DataType data)
{if (list == NULL) {return;}if (list->count == 0) {Node* node = create_node(data);assert(node);list->headNode = node;}else {Node* node = create_node(data);assert(node);node->next = list->headNode;list->headNode = node;}list->count++;
}void push_back(List* list, DataType data)
{if (list == NULL) {return;}if (list->count == 0) {push_front(list, data); // 相当于头插}else {Node* cur = list->headNode;while (cur->next) {cur = cur->next;}Node* node = create_node(data);assert(node);cur->next = node;}list->count++;
}// 这里定义,在找到数据后位置插入
void insert(List* list, DataType posData, DataType insertData)
{if (list == NULL || list->count == 0)return;Node* cur = list->headNode;while (cur->next && cur->data != posData) {cur = cur->next;}// cur->next == null, cur->data == posdataif (cur->data != posData) {return;}else {Node* node = create_node(insertData);assert(node);node->next = cur->next;cur->next = node;}list->count++;
}void pop_front(List* list)
{if (list == NULL || list->count == 0)return;if (list->count == 1) {Node* t = list->headNode;list->headNode = NULL;free(t);t = NULL;}else {Node* t = list->headNode;list->headNode = t->next;free(t);t = NULL;}list->count--;
}void pop_back(List* list)
{if (list == NULL || list->count == 0)return;if (list->headNode->next == NULL) {free(list->headNode);list->headNode = NULL;}else {// 双指针Node* pre = list->headNode;Node* tail = list->headNode->next;while (tail->next != NULL) {pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}list->count--;
}void earse(List* list, DataType data)
{if (list == NULL || list->count == 0)return;Node* pre = NULL;Node* pos = list->headNode;// 没有到终点,且没有找到datawhile (pos != NULL && pos->data != data) {pre = pos;pos = pre->next;}if (pos == NULL) {return;}else if(pre == NULL){pop_front(list);}else {pre->next = pos->next;free(pos);pos = NULL;}list->count--;
}void travel(List* list)
{if (list == NULL) {return;}Node* cur = list->headNode;while (cur) {printf("%d ", cur->data);cur = cur->next;}printf("\n");
}int main()
{List* list = create_list();push_front(list, 1);push_front(list, 2);push_front(list, 3);push_back(list, 4);push_back(list, 5);push_back(list, 6);travel(list);insert(list, 2, 22);insert(list, 6, 66);travel(list);pop_front(list);travel(list);pop_back(list);travel(list);earse(list, 22);earse(list, 6);travel(list);return 0;
}

二级指针写法

二级指针的写法主要在于创建节点的时候,

📦 节点封装

typedef int DataType;typedef struct Node {DataType data;struct Node* next;
}Node;

🍨 创建节点

Node* create_node(DataType data)
{Node* node = calloc(1, sizeof(Node));if (node == NULL) {return node;}node->data = data;return node;
}

🤕 插入–头插入:

void push_front(Node** list, DataType data)
{if (list == NULL) {return;}Node* new_node = create_node(data);if (*list == NULL) {*list = new_node;}else {new_node->next = *list;*list = new_node;}
}

🚖 插入–尾插入

void push_back(Node** list, DataType data)
{if (list == NULL) {return;}// 无头if (*list == NULL) {*list = create_node(data);}else {Node* pos = (*list);Node* cur = (*list)->next;while (cur) {pos = cur;cur = cur->next;}pos->next = create_node(data);}}

⚡️ 插入–指定数据后插入:

// 在posData数据后插入
void insert(Node** list, DataType posData, DataType data)
{// *list == null,说明链表为空if (list == NULL || *list == NULL) {return;}Node* pos = *list;while (pos != NULL && pos->data != posData) {pos = pos->next;}// 不存在该节点if (pos == NULL) {return;}else {Node* t = create_node(data);t->next = pos->next;pos->next = t;}}

📚 总代码:

#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>typedef int DataType;typedef struct Node {DataType data;struct Node* next;
}Node;Node* create_node(DataType data)
{Node* node = calloc(1, sizeof(Node));if (node == NULL) {return node;}node->data = data;return node;
}void push_front(Node** list, DataType data)
{if (list == NULL) {return;}Node* new_node = create_node(data);if (*list == NULL) {*list = new_node;}else {new_node->next = *list;*list = new_node;}
}void push_back(Node** list, DataType data)
{if (list == NULL) {return;}// 无头if (*list == NULL) {*list = create_node(data);}else {Node* pos = (*list);Node* cur = (*list)->next;while (cur) {pos = cur;cur = cur->next;}pos->next = create_node(data);}}
// 在posData数据后插入
void insert(Node** list, DataType posData, DataType data)
{// *list == null,说明链表为空if (list == NULL || *list == NULL) {return;}Node* pos = *list;while (pos != NULL && pos->data != posData) {pos = pos->next;}// 不存在该节点if (pos == NULL) {return;}else {Node* t = create_node(data);t->next = pos->next;pos->next = t;}}void travel(Node* list)
{if (list == NULL) {return;}Node* cur = list;while (cur) {printf("%d ", cur->data);cur = cur->next;}printf("\n");
}int main()
{Node* list = NULL;push_front(&list, 1);push_front(&list, 2);push_front(&list, 3);travel(list);push_back(&list, 4);push_back(&list, 5);push_back(&list, 6);travel(list);insert(&list, 4, 44);insert(&list, 1, 11);travel(list);return 0;
}

👨‍🏭单链表的一些操作

🏀 准备工作:本次案例均采用有头链表进行操作,创建有头链表,与尾插法、遍历链表代码如下:

typedef struct Node {int data;struct Node* next;
}Node;Node* create_list()
{Node* list = (Node*)calloc(1, sizeof(Node));assert(list);return list;
}Node* create_node(int data)
{Node* node = (Node*)calloc(1, sizeof(Node));assert(node);node->data = data;return node;
}// 插入
void push_back(Node* list, int data)
{assert(list);Node* headNode = list->next;if (headNode == NULL) {headNode = create_node(data);list->next = headNode;}else {Node* prev = NULL;Node* cur = headNode;while (cur != NULL) {prev = cur;cur = cur->next;}prev->next = create_node(data);}
}// 遍历
void travel(Node* list)
{assert(list);Node* curNode = list->next;while (curNode) {printf("%d ", curNode->data);curNode = curNode->next;}printf("\n");
}

注意、注意: 下面案例如果设计有序,默认是升序。

有序链表的构建

🔊 其实这个,就是插入排序的思想,在插入的时候,找到数据小于链表中某一个节点数据的第一个节点,有点绕,看代码会容易很多,然后就是正常的链表的插入了。

// 有序链表的构建
void push_sort(Node* list, int data)
{assert(list);Node* headNode = list->next;if (headNode == NULL) {headNode = create_node(data);list->next = headNode;}else {Node* prev = NULL;Node* curNode = headNode;while (curNode != NULL && curNode->data < data) {   // 找prev = curNode;curNode = curNode->next;}Node* node = create_node(data);// 头插if (prev == NULL) {node->next = list->next;list->next = node;}else {  // 找到第一个大于data、或者data是最大的情况node->next = prev->next;prev->next = node;}}
}

排序链表

🚅 这里仅采用最简单的算法,冒泡:

void bubble_sort(Node* list)
{assert(list);for (Node* i = list->next; i != NULL; i = i->next) {for (Node* j = list->next; j != NULL; j = j->next) {if (j->next != NULL && j->data > j->next->data) {int temp = j->data;j->data = j->next->data;j->next->data = temp;}}}
}

链表反转

🔙 其中,创建3个辅助指针,next 找节点,反转:prev与curNode指针不断转换的过程

void reversed(Node* list)
{// 至少需要两个节点if (list == NULL || list->next == NULL || list->next->next == NULL) {return;}Node* prev = NULL;Node* curNode = list->next;Node* nextNode = curNode->next;while (nextNode != NULL) {curNode->next = prev;prev = curNode;curNode = nextNode;nextNode = nextNode->next;}curNode->next = prev;list->next = curNode;
}

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

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

相关文章

Python | Leetcode Python题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; class Solution:def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:m, n len(matrix), len(matrix[0])# 初始化动态规划的数组&#xff0c;所有的距离值都设置为一个很大的数dist [[10**9] * n for _ in range(m)]…

ENSP作业——园区网

题目 根据上图&#xff0c;可得需求为&#xff1a; 1.配置交换机上的VLAN及IP地址。 2.设置SW1为VLAN 2/3的主根桥&#xff0c;设置SW2为VLAN 20/30的主根桥&#xff0c;且两台交换机互为主备。 3.可以使用super vlan。 4.上层通过静态路由协议完成数据通信过程。 5.AR1作为企…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第7天,申请阿里云SMS短信服务SDK

系列专栏链接如下&#xff0c;方便跟进&#xff1a; https://blog.csdn.net/weixin_62588253/category_12821860.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12821860&sharereferPC&sharesourceweixin_62588253&sharefromfrom_link 同时篇幅…

让Apache正确处理不同编码的文件避免中文乱码

安装了apache2.4.39以后&#xff0c;默认编码是UTF-8&#xff0c;不管你文件是什么编码&#xff0c;统统按这个来解析&#xff0c;因此 GB2312编码文件内的中文将显示为乱码。 <!doctype html> <html> <head><meta http-equiv"Content-Type" c…

『Django』初识前后端分离

点赞 + 关注 + 收藏 = 学会了 本文简介 在前面的「Django」系列的文章 中使用的是“前后端不分离”的方式去学习 Django,但现在企业比较流行的开发方式是前后端分离。 简单来说,前后端分离就是把前端和后端的工作分配给2个人做,前端主要负责用户界面的开发,后端主要负责…

探索开放资源上指令微调语言模型的现状

人工智能咨询培训老师叶梓 转载标明出处 开放模型在经过适当的指令调整后&#xff0c;性能可以与最先进的专有模型相媲美。但目前缺乏全面的评估&#xff0c;使得跨模型比较变得困难。来自Allen Institute for AI和华盛顿大学的研究人员们进行了一项全面的研究&#xff0c;探索…

搜维尔科技:【应用】Xsens在荷兰车辆管理局人体工程学评估中的应用

荷兰车辆管理局&#xff08;RDW&#xff09;通过数据驱动的人体工程学评估&#xff0c;将职业健康和安全放在首位。 关键信息 01 改进人体工程学评估&#xff1a;RDW使用Xsens动作捕捉和Scalefit Industrial Athlete进行精确、实时的人体工程学评估&#xff0c;识别并降低与…

文件系统和日志管理 附实验:远程访问第一台虚拟机日志

文件系统和日志管理 文件系统&#xff1a;文件系统提供了一个接口&#xff0c;用户用来访问硬件设备&#xff08;硬盘&#xff09;。 硬件设备上对文件的管理 文件存储在硬盘上&#xff0c;硬盘最小的存储单位是512字节&#xff0c;扇区。 文件在硬盘上的最小存储单位&…

大众汽车合肥社招入职笔试测评SHL题库:综合能力、性格问卷、英语口语真题考什么?

大众汽车合肥社招入职笔试测评包括综合能力测试、性格问卷和英语口语测试。以下是各部分的具体内容&#xff1a; 1. **综合能力测试**&#xff1a; - 这部分测试需要46分钟完成&#xff0c;建议准备计算器和纸笔。 - 测试内容涉及问题解决能力、数值计算能力和逻辑推理能力。 -…

Python进阶之IO操作

文章目录 一、文件的读取二、文件内容的写入三、之操作文件夹四、StringIO与BytesIO 一、文件的读取 在python里面&#xff0c;可以使用open函数来打开文件&#xff0c;具体语法如下&#xff1a; open(filename, mode)filename&#xff1a;文件名&#xff0c;一般包括该文件所…

UE5.4 PCG 自定义PCG蓝图节点

ExecuteWithContext&#xff1a; PointLoopBody&#xff1a; 效果&#xff1a;点密度值与缩放成正比

Transformer和BERT的区别

Transformer和BERT的区别比较表&#xff1a; 两者的位置编码&#xff1a; 为什么要对位置进行编码&#xff1f; Attention提取特征的时候&#xff0c;可以获取全局每个词对之间的关系&#xff0c;但是并没有显式保留时序信息&#xff0c;或者说位置信息。就算打乱序列中token…

Apache Commons Collections 反序列化漏洞

文章目录 前言一、漏洞爆出二、复现环境java集合框架问题JVM反射 三、Apache Commons Collections漏洞原理≤3.2.1CC关键类调用链路POC构造思路POC 前言 Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库&#xff0c;它提供了很多强大的数据…

正则表达式1 re.match惰性匹配详解案例

点个关注 re.match() re.match() 函数尝试从字符串的开头开始匹配一个模式&#xff0c;如果匹配成功&#xff0c;返回一个匹配成功的对象&#xff0c;否则返回None。大小写区分&#xff0c;内容匹配不到后面的,只能匹配一个&#xff0c;不能有空格&#xff08;开头匹配&#…

gov企业征信系统瑞数6vmp算法还原

URL aHR0cHM6Ly9zZC5nc3h0Lmdvdi5jbi8今天再来逆向下国家企业征信系统&#xff0c;这个站很卡&#xff0c;兄弟们你们轻点爬&#xff0c;我刷以下页面就转好久的圈圈&#xff0c;这个站两层防护&#xff0c;一层加速乐&#xff0c;一层瑞数&#xff0c;貌似还有极验验证码防护…

代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础

目录 图论理论基础 深度优先搜索理论基础 卡玛网 98.所有可达路径 广度优先搜索理论基础 图论理论基础 图论理论基础 | 代码随想录 图的基本概念 图的种类 大体分为有向图和无向图。 图中的边有方向的是有向图&#xff1a; 图中的边没有方向的是无向图&#xff1a; 图…

【自学笔记】神经网络(1)

文章目录 介绍模型结构层&#xff08;Layer&#xff09;神经元 前向传播反向传播Q1: 为什么要用向量Q2: 不用激活函数会发生什么 介绍 我们已经学习了简单的分类任务和回归任务&#xff0c;也认识了逻辑回归和正则化等技巧&#xff0c;已经可以搭建一个简单的神经网络模型了。 …

详解Python面向对象程序设计

Python面向对象程序设计 1&#xff0c;初识类和对象2&#xff0c;类的定义和使用3&#xff0c;构造方法4&#xff0c;常用的类内置方法4.1&#xff0c;字符串方法&#xff1a;__str__ 4.2&#xff0c;是否小于&#xff1a;__lt__4.3&#xff0c;是否小于等于&#xff1a;__le__…

超级大项目招标:1000台AGV,12月13日截至

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 近期&#xff0c;一个重磅招标项目引发业界广泛关注&#xff1a;焦作机器人应用产业研究院发布总额高达11380万元的机器人采购项目&#xff0c;其中包括1000台AGV&#xff08;无人叉车…

内部知识库:优化企业培训流程的关键驱动力

在当今快速变化的商业环境中&#xff0c;企业培训的重要性日益凸显。内部知识库作为整合、管理和分享企业内部学习资源的关键工具&#xff0c;正逐步成为优化企业培训流程的核心。以下将探讨内部知识库如何通过多种功能&#xff0c;助力企业提升培训效率、质量和员工满意度。 …