栈和队列学习

栈和队列学习

使用到的链表函数

  • 链式队列和链式栈都用到了链表的一些函数,在这里声明
// 定义链表
struct Node {
  int data;
  struct Node* next;
};

// 创建链表头
struct Node* createList() {
  struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
  headNode->next = NULL;
  return headNode;
}

// 创建节点 (和创建链表头基本相同)
struct Node* createNode(int data) {
  struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
  newNode->data = data;
  newNode->next = NULL;
  return newNode;
}

链式栈 (Stack)

  • 栈:先进后出
  • 和链表的表头插入法特别像 (和链表唯一的区别就是栈没有头节点)

链式栈的定义

  • 链式栈和链表特别像
  • 代码示例:
// 定义链表
struct Node {
  int data;
  struct Node* next;
};

// 定义栈
struct Stack {
  struct Node* topStack;
  int size;
};
  • 在定义链表的外部新增栈顶指针 (topStack) 和 栈的元素个数 (size)

初始化栈

  • 为栈分配内存空间,初始化栈的两个值
  • 代码示例:
// 初始化栈
struct Stack* createStack() {
  // 分配内存空间
  struct Stack* newStack = (struct Stack*)malloc(sizeof(struct Stack));
  // 初始化两个值
  newStack->size = 0;
  newStack->topStack = NULL;
  return newStack;
}

入栈 (push)

  • 栈比较特殊,他没有头节点,第一个入栈的相当于链表的最后一个元素 (很符合先进后出的原理)

  • 然后类似于头插法,只不过没有头节点,所以只需要插入的元素指向下一个元素,不需要有其他元素指向它 (直到下一个元素要入栈时)

  • 代码示例:

// 入栈操作(push)
void pushStack(struct Stack* stack,int data) {
  // 新建一个节点
  struct Node* newNode = createNode(data);
  // 新节点指向上一个入栈的元素
  newNode->next = stack->topStack;
  // 栈顶指针指向新入栈的元素
  stack->topStack = newNode;
  // 栈的大小加一
  stack->size++;
}
  • 看这个图片应该能更好理解
    Stack

读取栈顶元素

  • 因为栈顶指针永远都指向栈顶,所以直接利用它就可以输出栈顶元素了
  • 代码示例:
// 读取栈顶元素
int topStack(struct Stack* stack) {
  // 栈不能为空
  if (stack->size == 0)
    return NULL;
  return stack->topStack->data;
}

出栈 (pop)

  • 类似于链表的删除,而且是只能从链表头开始删除的那种
  • 删除步骤就是先将下一个元素的地址用一个中间变量指针保存起来,然后栈顶指针 (topStack) 指向下一个元素,然后 free 掉上一个节点就可以了
  • 通过判断 size 的值来判断链表是否为空
  • 代码示例:
// 出栈
void popStack(struct Stack* stack) {
  if (stack->size == 0)
    cout << "栈为空,无法出栈" << endl;
  else
  {
    // 先临时保存下一个节点的地址
    struct Node* nextNode = stack->topStack->next;
    // free掉上一个节点
    free(stack->topStack);
    // 栈顶指针指向下一个节点
    stack->topStack = nextNode;
    nextNode = NULL;
    stack->size--;
  }
}

栈的主函数

  • 测试栈的函数:
int main() {
  struct Stack* myStack = createStack();
  for (int i = 0; i < 5; i++) {
    pushStack(myStack, i);
  }
  for (int i = 0; i < 5; i++) {
    cout << topStack(myStack) <<"\t"<< endl;
    popStack(myStack);
  }
  return 0;
}

// 输出结果
// 4
// 3
// 2
// 1
// 0

链式队列

  • 队列:先进先出
  • 和尾插法特别像 (同样没有头节点)

链式队列的定义

  • 创建一个结构体,里面包括头节点,尾节点和队列长度
  • 代码示例:
// 定义队列
struct Queue {
  struct Node* frontNode; // 头节点
  struct Node* tailNode;  // 尾节点
  int size;  // 队列大小
};

创建队列

  • 分配内存空间,并且给里面的数据赋初值
  • 代码示例:
// 创建队列
struct Queue* createQueue() {
  // 分配内存空间
  struct Queue* myQueue = (struct Queue*)malloc(sizeof(struct Queue));
  // 赋初值
  myQueue->frontNode = myQueue->tailNode = NULL;
  myQueue->size = 0;
  return myQueue;
}

入队

  • 入队分成两种情况,一种队为空时,另一种队不为空时
    • 队为空时入队队里只有一个元素,这时头节点和尾节点都指向那唯一一个元素
    • 对不为空时头节点指向头元素,尾节点指向尾元素
  • 代码示例:
// 入队
void pushQueue(struct Queue* myQueue,int data) {
  // 新建一个节点
  struct Node* newNode = createNode(data);
  // 如果队为0,那么头节点和尾节点都指向第一个入队的元素
  if (myQueue->size == 0) {
    myQueue->frontNode = myQueue->tailNode = newNode;
  }
   // 队里面有两个及以上的元素时,头节点不变,尾节点向后移动一位
  else {
    myQueue->tailNode->next = newNode;
    myQueue->tailNode = newNode;
    myQueue->size++;
  }
  // 队列长度加一
  myQueue->size++;
}

出队

  • 先把队头元素的下一个元素的地址储存起来,然后 free 掉队头元素 (frontNode指向的元素),然后队头指针 (frontNode) 指向刚开始储存的地址
  • 代码示例:
// 出队
void popQueue(struct Queue* myQueue) {
  if (myQueue->size == 0) {
    cout << "栈为空" << endl;
  }
  else
  {
    // 暂存下一个元素地址
    struct Node* nextNode = myQueue->frontNode->next;
    free(myQueue->frontNode);
    // 指向刚才储存的元素地址
    myQueue->frontNode = nextNode;
    myQueue->size--;
  }
}

获取队顶元素

  • 先判断一下队是否为空,然后返回 frontNode 指向的元素就可以了
  • 代码示例:
// 获取队顶元素
int frontQueue(struct Queue* myQueue) {
  if (myQueue->size == 0) {
    cout << "栈为空" << endl;
    return NULL;
  }
  else {
    return myQueue->frontNode->data;
  }
}

队列主函数

  • 测试上面所写的函数
int main() {
  struct Queue* myQueue = createQueue();
  for (int i = 0; i < 5; i++) {
    pushQueue(myQueue, i);
  }
  // myQueue = {0,1,2,3,4}
  for (int i = 0; i < 5; i++) {
    cout << frontQueue(myQueue) << endl;
    popQueue(myQueue);
  }
  return 0;
}

// 输出结果:
// 0
// 1
// 2
// 3
// 4
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值