C语言双向链表

当涉及到双向链表时,使用一个头结点(也称作哨兵节点)可以简化一些操作,比如插入和删除节点的操作。头结点是一个特殊的节点,它位于链表的开始位置,不存储任何实际数据,但使得链表的一些边界情况更容易处理。

下面我们将详细讨论如何实现一个带有头结点的双向链表。

1. 定义节点结构体

首先定义一个结构体来表示双向链表中的节点。

 

c

深色版本

1typedef struct Node {
2    int data;       // 存储的数据
3    struct Node *next;  // 指向下一个节点的指针
4    struct Node *prev;  // 指向前一个节点的指针
5} Node;

2. 初始化链表

定义一个函数来初始化链表,即创建一个空的头结点。

 

c

深色版本

1Node* initList() {
2    Node* head = (Node*)malloc(sizeof(Node));
3    if (head == NULL) {
4        printf("Memory allocation failed\n");
5        return NULL;
6    }
7    head->data = 0;     // 可以设置为任意值,因为不会被使用
8    head->next = NULL;
9    head->prev = NULL;
10    return head;
11}

3. 在链表头部插入节点

定义一个函数来在链表的头部插入一个新节点。

 

c

深色版本

1void insertAtHead(Node* head, int value) {
2    Node* newNode = (Node*)malloc(sizeof(Node));
3    if (newNode == NULL) {
4        printf("Memory allocation failed\n");
5        return;
6    }
7    newNode->data = value;
8    newNode->next = head->next;
9    newNode->prev = head;
10    
11    if (head->next != NULL) {
12        head->next->prev = newNode;
13    }
14    head->next = newNode;
15}

4. 在链表尾部插入节点

定义一个函数来在链表的尾部插入一个新节点。

 

c

深色版本

1void insertAtTail(Node* head, int value) {
2    Node* newNode = (Node*)malloc(sizeof(Node));
3    if (newNode == NULL) {
4        printf("Memory allocation failed\n");
5        return;
6    }
7    newNode->data = value;
8    newNode->next = NULL;
9    newNode->prev = head->prev;
10    
11    if (head->prev != NULL) {
12        head->prev->next = newNode;
13    }
14    head->prev = newNode;
15}

5. 删除链表中的节点

定义一个函数来删除链表中的指定节点。

 

c

深色版本

1void deleteNode(Node* head, Node* nodeToDelete) {
2    if (nodeToDelete == NULL) return;
3
4    if (nodeToDelete->prev != NULL)
5        nodeToDelete->prev->next = nodeToDelete->next;
6    else
7        head->next = nodeToDelete->next;
8
9    if (nodeToDelete->next != NULL)
10        nodeToDelete->next->prev = nodeToDelete->prev;
11    else
12        head->prev = nodeToDelete->prev;
13
14    free(nodeToDelete);
15}

6. 遍历链表

定义一个函数来遍历并打印链表中的所有节点。

 

c

深色版本

1void printList(Node* head) {
2    Node* temp = head->next;
3    while (temp != NULL) {
4        printf("%d ", temp->data);
5        temp = temp->next;
6    }
7    printf("\n");
8}

7. 示例程序

下面是一个完整的示例程序,演示如何使用上述定义的函数。

 

c

深色版本

1#include <stdio.h>
2#include <stdlib.h>
3
4// 之前定义的 Node 结构体和相关函数
5
6int main() {
7    Node* head = initList();
8    
9    insertAtHead(head, 10);
10    insertAtHead(head, 20);
11    insertAtTail(head, 30);
12    insertAtTail(head, 40);
13    
14    printf("Linked list after insertions: ");
15    printList(head);
16
17    deleteNode(head, head->next);  // 删除第一个节点
18
19    printf("Linked list after deleting the first node: ");
20    printList(head);
21
22    return 0;
23}

注意事项

  • 在实际应用中,通常会使用一个指针指向头结点,而不是指向真正的数据节点。
  • 当删除链表中的最后一个节点时,需要更新头结点的prev指针。
  • 当在链表头部插入节点时,需要确保更新头结点的next指针以及新节点的prev指针。
  • 当在链表尾部插入节点时,需要确保更新头结点的prev指针以及新节点的next指针。

以上就是带有一个头结点的双向链表的基本实现。你可以在此基础上进一步扩展功能,例如实现反转链表、查找节点等功能。

  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值