数据结构与算法C语言版学习笔记(4)-栈与队列再回顾

news2024/11/23 8:37:17

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言:
  • 一、栈的定义:栈(stack)是限定仅在表尾进行插入和删除操作的线性表
    • (1)栈是特殊的线性表
    • (2)入栈与出栈
  • 二、栈的顺序存储结构与代码操作实现
    • (1)顺序栈的结构
    • (2)进栈操作
    • (3)出栈操作
  • 三、栈的链式存储结构与代码操作实现
    • (1)链式栈的结构
    • (2)链式栈的入栈操作和出栈操作
  • 四、栈有什么用处?
    • 1.举几个例子
    • 2.具体应用——递归:求斐波那契数列前n项的数
      • ①斐波那契数列:0,1,1,2,3,5,8,13,.......。其前两项为0和1,之后每一项都是前两项之和。
      • ②常规解法:
      • ③递归解法:
      • ④递归函数与栈有什么关系?
  • 五、队列
    • 1.队列是什么?
    • 2.队列的顺序结构
    • 3.队列的链式结构
    • 4.队列有什么作用?
  • 六、栈和队列的总结


前言:

在使用嵌入式单片机开发时,经常会用到栈和队列的知识。
比如:
栈:
函数调用:嵌入式系统中的函数调用通常使用栈来保存函数的上下文信息。每当一个函数被调用,函数的参数、局部变量以及返回地址等信息都会被保存在栈中,待函数执行完毕后再从栈中恢复上下文。
中断处理:当一个中断被触发时,嵌入式系统会将当前的执行状态保存在栈中,然后跳转到中断服务程序进行处理。处理完毕后,再从栈中恢复之前的执行状态。
数据结构:栈常用于实现其他数据结构,如深度优先搜索算法(DFS)中使用的递归调用,以及表达式求值中的操作符栈等。

队列:
任务调度:嵌入式系统中的任务调度器通常使用队列来管理任务的执行顺序。通过队列,可以按照一定的优先级或者时间片轮转的方式来调度任务的执行。
事件处理:嵌入式系统中的事件处理机制通常使用队列来存储和处理事件。当一个事件发生时,会将事件放入队列中,然后由相应的任务或中断服务程序来处理队列中的事件。
缓冲区管理:嵌入式系统中的通信和数据处理往往需要使用缓冲区来存储数据。队列可以作为缓冲区的管理机制,用于存储和传输数据。

所以栈和队列非常重要。

一、栈的定义:栈(stack)是限定仅在表尾进行插入和删除操作的线性表

在我们软件应用中,栈这种后进先出数据结构的应用是非常普遍的。比如你用浏览器上网时,不管什么浏览器都有一个“后退”键,你点击后可以按访问顺序的逆序加载浏览过的网页。比如你本来看着新闻好好的,突然看到一个链接说,有个可以让你年薪100万的工作,你毫不犹豫点击它,跳转进去一看,这都是啥呀,具体内容我也就不说了,骗人骗得一点水平都没有。此时你还想回去继续看新闻,就可以点击左上角的后退键。即使你从一个网页开始,连续点了几十个链接跳转,你点“后退”时,还是可以像历史倒退一样,回到之前浏览过的某个页面

给定一下:栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
(1)我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底 (bottom),不含任何数据元素的栈称为空栈。
(2)栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。

(1)栈是特殊的线性表

栈是一种特殊的线性表,它只允许在表的一端进行插入和删除操作,该端称为栈顶(Top)。栈按照“后进先出”(Last In First Out,LIFO)的原则进行操作,最后插入的元素最先被删除。

与普通的线性表不同,栈只支持在栈顶进行插入(压入)和删除(弹出)操作,而不允许在栈底或中间进行操作。当一个新元素被插入到栈中时,它成为新的栈顶;当一个元素被删除时,栈顶指针指向下一个元素,成为新的栈顶。

(2)入栈与出栈

在这里插入图片描述
入栈与出栈会有很多种不同的可能,只要遵循栈顶的元素先出的原则即可。
在这里插入图片描述
在这里插入图片描述

二、栈的顺序存储结构与代码操作实现

(1)顺序栈的结构

在这里插入图片描述
两个结构体成员,分别是数据域data和一个记录栈顶元素位置的变量top。由于顺序栈就是个数组,所以初始化栈时,栈空间是确定的,大小为MAXSIZE,所以栈内元素不能超出上限,否则就会发生堆栈溢出。
在这里插入图片描述
对顺序栈,即数组而言,栈顶就是下标为0的位置,空栈时栈顶变量为下标-1,进栈后栈顶变量动态变化,总是指向栈顶的那个元素。
这里要注意一个关键:top变量不是指针变量,而是一个整型变量,它记录的是栈顶元素在数组中的下标大小。

(2)进栈操作

思路:对于栈数组,进栈一个元素,那么栈指针增加一位,指向该元素。由于数组的特性,数组的首个元素的下标即为指针地址,所以第二个元素的指针地址,就是指针+1来表示,同理第三个就是+2。
在这里插入图片描述
代码:

#include <stdio.h>
#define MAX_SIZE 10

// 定义顺序栈结构体
typedef struct {
    int data[MAX_SIZE]; // 用数组存储栈的元素
    int top; // 栈顶指针
} Stack;

// 初始化栈
void initStack(Stack *stack) {
    stack->top = -1; // 栈顶指针初始化为-1
}

// 判断栈是否为空
int isEmpty(Stack *stack) {
    return stack->top == -1;
}

// 判断栈是否已满
int isFull(Stack *stack) {
    return stack->top == MAX_SIZE - 1;
}

// 入栈操作
void push(Stack *stack, int element) {
    if (isFull(stack)) {
        printf("Stack is full. Cannot push element.\n");
        return;
    }
    stack->top++; // 栈顶指针加1
    stack->data[stack->top] = element; // 将元素存入栈顶位置
    printf("Element %d pushed into stack.\n", element);
}

int main() {
    Stack stack;
    initStack(&stack);

    int element = 10;
    push(&stack, element);

    return 0;
}

一开始,top变量值为-1,当有一个元素入栈时,top++变为0,即数组的第一个元素,给第一个元素赋值,就完成了入栈操作。

(3)出栈操作

思路:对于stack->data[stack->top],先赋值给一个变量,然后将stack->top–.
在这里插入图片描述

三、栈的链式存储结构与代码操作实现

(1)链式栈的结构

想想看,栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?由于单链表有头指针,而栈顶指针也是必须的,那干吗不让它俩合二为一呢,所以比较好的办法是把栈顶放在单链表的头部(如图4-6-1所示)。另外,都已经有了栈顶在头部了,单链表中比较常用的头结点也就失去了意义,通常对于链栈来说,是不需要头结点的。

在这里插入图片描述
链栈由于链式结构的特性,所占空间是动态变化的,所以不会出现堆栈溢出的情况。而顺序结构由于空间提前定义好了,所以无法改变,可能会出现溢出。

在这里插入图片描述
这里有两个结构体,一个是栈的节点(数据域+指针域,与链表一致),另一个是链栈(栈顶指针top)。

(2)链式栈的入栈操作和出栈操作

思路:
①链栈入栈:将新节点插入到链表头部,然后更新栈顶指针。

// 入栈操作
void push(Stack* stack, int element) {
    Node* newNode = (Node*)malloc(sizeof(Node)); // 创建新节点
    if (newNode == NULL) {
        printf("Memory allocation failed. Cannot push element.\n");
        return;
    }
    newNode->data = element; // 设置新节点的数据元素
    newNode->next = stack->top; // 将新节点插入到链表头部
    stack->top = newNode; // 更新栈顶指针
    printf("Element %d pushed into stack.\n", element);
}

②出栈:保存栈顶节点的地址到temp,保存栈顶节点的数据元素到poppedElement,更新栈顶指针top为栈顶节点的下一个节点,释放temp指向的节点内存。

// 出栈操作
void pop(Stack* stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty. Cannot pop element.\n");
        return;
    }
    Node* temp = stack->top; // 保存栈顶节点的地址
    int poppedElement = temp->data; // 保存栈顶节点的数据元素
    stack->top = temp->next; // 更新栈顶指针
    free(temp); // 释放栈顶节点的内存
    printf("Element %d popped from stack.\n", poppedElement);
}

四、栈有什么用处?

1.举几个例子

在计算机科学和编程中有广泛的应用,以下是一些栈的常见用途:

函数调用:栈用于存储函数调用时的局部变量、返回地址和函数参数等信息。当一个函数被调用时,它的局部变量和参数被压入栈中,函数执行完毕后再从栈中弹出这些信息,返回到调用点。

表达式求值:栈可以用于解析和求解数学表达式,如中缀表达式(常见的数学表达式表示方式),通过将操作符和操作数入栈并按照一定规则弹出和计算,可以实现表达式的求值。

括号匹配:栈可以用于检查表达式中的括号是否匹配。通过遍历表达式,将左括号入栈,遇到右括号时弹出栈顶元素并检查是否匹配,如果匹配则继续,否则表达式中的括号不匹配。

浏览器的历史记录:浏览器的历史记录可以使用栈来实现。每次访问一个新的网页时,将该网页入栈,当点击返回按钮时,从栈中弹出最近访问的网页,实现浏览器的返回功能。

撤销操作:在文本编辑器、图形软件等应用程序中,栈可以用于实现撤销操作。每次进行修改操作时,将修改前的状态入栈,当需要撤销操作时,从栈中弹出最近的状态,恢复到该状态。

2.具体应用——递归:求斐波那契数列前n项的数

①斐波那契数列:0,1,1,2,3,5,8,13,…。其前两项为0和1,之后每一项都是前两项之和。

②常规解法:

void Feb(int n){
for(i = 2;i < n;i++){
a[i]=a[i-1]+a[i-2];
printf("%d  ", a[i]);
}

int main(){
Feb(20);
return 0;

不解释了。

③递归解法:

int fibonacci(int n) {
    if (n == 0 || n == 1) {
        return n;
    } else {
        return fibonacci(n-1) + fibonacci(n-2);
    }
}

递归是什么意思呢?就是说一个函数在运行时调用了另外一个函数,只不过这个函数正好是它自己,而函数的传参不同。在高级语言中,调用自己和其它函数并没有本质的不同。我们把一个直接调用自
己或通过一系列的调用语句间接地调用自己的函数,称做递归函数。

递归程序最怕的就是陷入永不结束的无穷递归中,所以,每个递归定义必须至少有一个条件,满足时递归不再进行,即不再引用自身而是返回值退出。比如例子,总有一次递归会使得 i<2的,这样就可以执行return i的语句而不用继续递归了。

④递归函数与栈有什么关系?

递归函数和栈之间有密切的关系。

在计算机中,每当一个函数被调用时,会在内存中创建一个称为“函数调用栈”或“调用栈”的数据结构。这个栈用于存储函数的局部变量、返回地址和其他与函数调用相关的信息。

当一个函数调用另一个函数时,当前函数的执行被暂停,并将当前函数的信息(包括局部变量、返回地址等)压入栈中,然后开始执行被调用的函数。当被调用的函数执行完毕后,栈顶的函数信息被弹出栈,并恢复到原来的函数继续执行。

递归函数就是在函数执行过程中调用自身的函数当递归函数被调用时,它会将自身的信息压入栈中,然后开始执行自身。当递归函数的终止条件满足时,递归开始回溯,即从栈中弹出函数信息并恢复上一层的函数继续执行。这个回溯的过程就是递归函数的出栈操作。

因此,递归函数的调用过程实际上就是对栈的操作。每次递归调用都会创建一个新的栈帧,将函数的局部变量和其他信息存储在该栈帧中。当递归结束时,栈会依次弹出栈帧,回到上一层函数的执行。

五、队列

1.队列是什么?

用电脑时有没有经历过,机器有时会处于疑似死机的状态,鼠标点什么似乎都没用,双击任何快捷方式都不动弹。就当你失去耐心,打算reset时。突然它像酒醒了一样,把你刚才点击的所有操作全部都按顺序执行了一遍。这其实是因为操作系统中的多个程序因需要通过一个通道输出,而按先后次序排队等待造成的
再比如像移动、联通、电信等客服电话,客服人员与客户相比总是少数,在所有的客服人员都占线的情况下,客户会被要求等待,直到有某个客服人员空下来,才能让最先等待的客户接通电话。这里也是将所有当前拨打客服电话的客户进行了排队处理
操作系统和客服系统中,都是应用了一种数据结构来实现刚才提到的先进先出的排队功能,这就是队列

所以:队列是一种先进先出 First 10 First 的线性衰,简称 FIFO 。允许插入的一端称为队尾,允许删除的一端称为队头。

在这里插入图片描述

2.队列的顺序结构

上代码:

#include <stdio.h>
#include <stdlib.h>

#define MAX_QUEUE_SIZE 10

typedef struct {
    int data[MAX_QUEUE_SIZE];
    int front;
    int rear;
} Queue;

void initQueue(Queue *q) {
    q->front = 0;
    q->rear = 0;
}

void enqueue(Queue *q, int value) {
    if ((q->rear + 1) % MAX_QUEUE_SIZE == q->front) {
        printf("Queue is full.\n");
        return;
    }
    q->data[q->rear] = value;
    q->rear = (q->rear + 1) % MAX_QUEUE_SIZE;
}

int dequeue(Queue *q) {
    if (q->front == q->rear) {
        printf("Queue is empty.\n");
        return -1;
    }
    int value = q->data[q->front];
    q->front = (q->front + 1) % MAX_QUEUE_SIZE;
    return value;
}

int main() {
    Queue q;
    initQueue(&q);

    enqueue(&q, 1);
    enqueue(&q, 2);
    enqueue(&q, 3);

    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q)); // Queue is empty.

    return 0;
}

定义了一个结构体Queue来表示队列,包含一个数组data用于存储队列元素,以及front和rear分别表示队头和队尾的下标。initQueue函数用于初始化队列,enqueue函数用于入队,dequeue函数用于出队。在入队和出队时,需要进行判断队列是否已满或已空,以防止出现越界访问的错误。

入队操作是将一个元素添加到队列的末尾。实现队列的顺序结构时,我们需要维护队列的rear指针,它指向队列的末尾元素。当我们要入队一个元素时,我们需要先检查队列是否已满。如果队列已满,则无法入队,否则可以将元素添加到队列末尾,并将rear指针后移一位。由于队列是先进先出的数据结构,新入队的元素总是在队列末尾,等待出队。

出队操作是将队列的头部元素移除,并返回它的值。实现队列的顺序结构时,我们需要维护队列的front指针,它指向队列的头部元素。当我们要出队一个元素时,我们需要先检查队列是否为空。如果队列为空,则无法出队,否则可以将队列的头部元素移除,并将front指针后移一位。由于队列是先进先出的数据结构,出队的元素总是队列中最早入队的元素。

3.队列的链式结构

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

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

typedef struct {
    Node *front;
    Node *rear;
} Queue;

void initQueue(Queue *q) {
    q->front = NULL;
    q->rear = NULL;
}

void enqueue(Queue *q, int value) {
    Node *newNode = (Node*) malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    if (q->rear == NULL) {
        q->front = newNode;
        q->rear = newNode;
    } else {
        q->rear->next = newNode;
        q->rear = newNode;
    }
}

int dequeue(Queue *q) {
    if (q->front == NULL) {
        printf("Queue is empty.\n");
        return -1;
    }

    int value = q->front->data;
    Node *temp = q->front;
    q->front = q->front->next;
    free(temp);

    if (q->front == NULL) {
        q->rear = NULL;
    }

    return value;
}

int main() {
    Queue q;
    initQueue(&q);

    enqueue(&q, 1);
    enqueue(&q, 2);
    enqueue(&q, 3);

    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q));
    printf("%d\n", dequeue(&q)); // Queue is empty.

    return 0;
}

链式队列的入队操作是在队列尾部添加一个新的元素,实现过程如下:
创建一个新节点,将要插入的元素值存储在新节点的数据域中。
将新节点的next指针指向队列的尾节点的下一个节点(即为NULL)。
将队列的尾节点的next指针指向新节点。
将队列的尾节点指针指向新节点。
如果队列为空,那么插入的新节点既是队列的头节点,也是队列的尾节点。

链式队列的出队操作是删除队列的头节点,实现过程如下:
如果队列为空,则无法进行出队操作,返回错误信息。
将头节点的数据域保存到一个临时变量中。
让头节点的指针指向下一个节点。
释放被删除的头节点。
如果队列为空,那么将尾节点的指针也置为NULL。

4.队列有什么作用?

队列是一种基本的数据结构,它可以在计算机科学中被广泛应用。以下是队列的一些主要应用:

1.任务调度:队列可以用于处理任务的调度,例如在操作系统中,可以使用队列来管理进程和线程的调度。

2.缓存管理:队列可以被用来管理缓存,例如在Web应用程序中,可以使用队列来处理缓存中的请求。

3.广度优先搜索:队列可以用于实现广度优先搜索算法,例如在图论中,可以使用队列来实现广度优先搜索。

4.消息传递:队列可以用于消息传递,例如在消息队列系统中,可以使用队列来传递和处理消息。

5.多线程编程:队列可以用于实现线程之间的通信,例如在多线程编程中,可以使用队列来传递数据和控制信息。

6.模拟系统:队列可以用于模拟系统的行为,例如在模拟排队系统中,可以使用队列来管理排队的顾客、服务员和服务窗口。

六、栈和队列的总结

栈和队列都是常用的数据结构,两者在概念上和实现上也有很多相似之处,但它们的操作方式和应用场景有很大的不同。

栈是一种后进先出(Last In First Out, LIFO)的数据结构,只允许在栈顶进行插入和删除操作,因此插入和删除的时间复杂度都是O(1)。栈的应用场景包括表达式求值、函数调用、回溯算法等。

队列是一种先进先出(First In First Out, FIFO)的数据结构,允许在队列尾部进行插入操作,在队列头部进行删除操作,因此插入和删除的时间复杂度都是O(1)。队列的应用场景包括广度优先搜索、缓存管理、CPU任务调度等。

在实现上,栈和队列都可以用数组或链表来实现。数组实现的栈和队列比较简单,但大小固定,需要预先分配空间。链表实现的栈和队列比较灵活,可以动态地添加和删除元素,但需要处理指针和内存管理问题。

综上所述,栈和队列是两种不同的数据结构,它们在应用场景和实现方式上都有很大的不同。在选择数据结构时,需要根据具体的需求来选择。

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

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

相关文章

元宇宙是否为噱头?若不是,什么是元宇宙?他的概念、技术、应用和影响是什么?

文章来源&#xff1a;元宇宙的概念、技术、应用与影响——一项系统性文献综述 - 中国知网 (cnki.net) 摘要 [目的/意义]系统综述与分析当前国内外的元宇宙研究现状&#xff0c;有利于准确把握元宇宙发展方向&#xff0c;强化元宇宙基础研究&#xff0c;争取元宇宙建构权。[方法…

Docker 学习路线 11:Docker命令行

Docker CLI (命令行界面) 是一个强大的工具&#xff0c;可让您与 Docker 容器、映像、卷和网络进行交互和管理。它为用户提供了广泛的命令&#xff0c;用于在其开发和生产工作流中创建、运行和管理 Docker 容器和其他 Docker 资源。 安装 要开始使用 Docker CLI&#xff0c;您…

企业计算机服务器中了360勒索病毒怎么办?勒索病毒解密,数据恢复

网络技术的不断发展给企业的生产与生活提供了极大的帮助&#xff0c;但随之而来的网络安全威胁也不断增加&#xff0c;近期&#xff0c;云天数据恢复中心的工程师接到了很多企业的求助&#xff0c;企业的计算机服务器数据库遭到了360后缀勒索病毒&#xff0c;通过对该病毒的检测…

Spring笔记(二)(黑马)(AOP面向切面编程)

01、AOP 简介 1.1 AOP的概念 AOP&#xff0c;Aspect Oriented Programming&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的…

2023年辽宁省数学建模竞赛B题数据驱动的水下导航适配区分类预测

2023年辽宁省数学建模竞赛 B题 数据驱动的水下导航适配区分类预测 原题再现&#xff1a; “海洋强国”战略部署已成为推动中国现代化建设的重要组成部分&#xff0c;国家对此提出“发展海洋经济&#xff0c;保护海洋生态环境&#xff0c;加快建设海洋强国”的明确要求。   …

PageHelper多表关联查询数量问题

PageHelper多表关联查询数量问题 通常我们会使用PageHelper进行分页查询&#xff0c;但是当分页查询被用到多个表的关联查询中时&#xff0c;就有可能导致查询出来的数据总数比我们想要的多得多。 首先在数据库中创建三个demo表&#xff1a;role、path、role_path role角色表…

每日一练 | 华为认证真题练习Day127

1、如图所示&#xff0c;关于OSPF的拓扑和配置&#xff0c;下列说法中正确的是&#xff08;&#xff09;。 A. R1与R2相比&#xff0c;R2更有机会成为DR&#xff0c;因为它的接口DR优先级值较小 B. 只要把R1的接口网络类型恢复为默认的广播类型&#xff0c;R1和R2即可建立稳定…

【可视化Java GUI程序设计教程】第5章 Swing容器的使用

Swing采用自顶向下的方式构建GUI&#xff0c;即先创建容器&#xff0c;再向容器中添加组件。 “组件”面板中的Swing容器 5.1 面板容器&#xff08;JPanel&#xff09; 5.5.1 使用方法 创建面板有以下两种方法 &#xff08;1&#xff09;创建一个窗体&#xff08;JFrame&…

kaggle中报错NameError: name ‘q_1‘ is not defined

在开始练习之前&#xff0c;先点击“全部运行”按钮。

联合阿里p8测试开发耗时一个月整理的全套从0开始到功能测试再到自动化测试再进阶测试开发学习路线图

前言&#xff1a; 从事测试工作已10有余了&#xff0c;今天想聊一下自己刚入门时和现在的今昔对比&#xff0c;虽然现在也没什么成就&#xff0c;只能说笑谈一下自己的测试生涯。 技术栈的变化&#xff1a; 刚开始是做的开发&#xff0c;也是做了三年的开发&#xff0c;刚开始…

工业CT 三维重建 及分割

目录 工业CT介绍 工业CT主要应用于以下领域&#xff1a; CT三维重建软件&#xff1a; 效果&#xff1a; 工业CT介绍 工业CT设备是基于线阵探测器的断层扫描技术&#xff0c;是一种常用的无损检测技术&#xff0c;用于获取物体内部的准确三维结构信息。它通过X射线的投射和接…

Linux - 实现一个简单的 shell

前言 之前我们对进程的替换&#xff0c;进程地址空间等等的概念进行了说明&#xff0c;本篇博客会基于这些知识点来 实现一个简单的 shell &#xff0c;如有疑问&#xff0c;可以参考下述博客&#xff1a;Linux - 进程程序替换 - C/C 如何实现与各个语言之间的相互调用 - 替换…

Spring Gateway基础知识总结

本文主要总结Spring Gateway的基础用法&#xff0c;内容包括网关、Spring Gateway工作流程、Spring Cloud Gateway搭建、路由配置方式、负载均衡实现、断言工厂这几个部分 目录 1. 网关 1.1 网关介绍 1.2 网关对比 1.3 Spring Gateway 1.4 核心概念 1.6 总结 2. Spring …

编程知识\_C与汇编深入分析

1. 汇编怎么调用C函数 1.1 直接调用 bl main 1.2 想传参数怎么办&#xff1f; 在arm中有个ATPCS规则(ARM-THUMB procedure call standard&#xff08;ARM-Thumb过程调用标准&#xff09;。 约定r0-r15寄存器的用途&#xff1a; r0-r3 调用者和被调用者之间传参数 r4-r11 函…

ARM寄存器及功能介绍/R0-R15寄存器

1、ARM 寄存器组介绍 ARM 处理器一般共有 37 个寄存器&#xff0c;其中包括&#xff1a; &#xff08;1&#xff09; 31 个通用寄存器&#xff0c;包括 PC&#xff08;程序计数器&#xff09;在内&#xff0c;都是 32 位的寄存器。 &#xff08;2&#xff09; 6 个状态寄存器…

Linux学习笔记--高级

Shell概述 1&#xff0c;shell概述 是一个c语言编写的脚本语言&#xff0c;是linux和用户的桥梁&#xff0c;用户输入命令交给shell处理。shell&#xff0c;将相应的操作传递给内核&#xff08;kernel&#xff09;&#xff0c;内核把处理的结果输出给用户 1.1Shell解释器有哪…

oled显示器程序(IIC)从stm32f103移植到stm32f429出现bug不显示-解决移植失败问题

出现问题处&#xff1a; 刚开始更换了这两行代码&#xff0c;然后更换位置后&#xff0c;oled正常显示&#xff0c;如下为正确顺序 I2C_Configuration();//配置CPU的硬件I2COLED_Init();//OLED初始化 在这段代码中&#xff0c;I2C_Configuration() 函数用于配置CPU的硬件 I2C…

阶段七-Day02-Spring02

一、Spring的注解支持 1. 为什么使用Spring注解 在昨天的练习中有这样的一段代码&#xff0c;为了给UserServiceImpl注入UserMapper对象。 2. Spring支持的注解&#xff08;IoC/DI相关&#xff09; 下面Repository、Service、Controller、Configuration都是Component注解的…

阴虱是怎么长出来的?皮肤性病科主任谭巍讲述五大因素

阴虱&#xff0c;是一种皮肤接触性传染性寄生虫病&#xff0c;在卫生情况不好的前提下有感染阴虱的可能性。人在感染阴虱后会对身心健康带来负面影响&#xff0c;所产生的临床症状会直接影响感染者的工作生活&#xff0c;所以日常应注意预防阴虱病。 然而&#xff0c;到现在还…

JS逆向爬虫---响应结果加密⑤【token参数加密与DES解密】

https://spa7.scrape.center/ 文本数据 数据内嵌在js内,普通合理请求即可获取 图片 位于固定接口 类似https://spa7.scrape.center/img/durant.png 固定url名称 Token 参数确定 base64Name > base64编码后的中文名称 nodejs 代码 //导入crypto-js模块 var CryptoJS…