• 【蓝桥杯】C语言常见数据结构


    🌸个人主页:Yang-ai-cao

    📕系列专栏:蓝桥杯    C语言

       🍍博学而日参省乎己,知明而行无过矣


    目录

    🌸个人主页:Yang-ai-cao

    📕系列专栏:蓝桥杯    C语言

       🍍博学而日参省乎己,知明而行无过矣

    一、 数组(Array)

    1、定义和初始化数组是一种线性数据结构,用于存储固定大小的相同类型元素。

    2、访问和修改元素

    3、常见操作

    - 遍历数组

    - 查找元素

    线性查找

    二分查找(适用于有序数组)

    - 排序数组(如冒泡排序、快速排序等)

    冒泡排序

    快速排序

    二、 链表(Linked List)

    1、定义节点结构链表是一种线性数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。

    2、创建和初始化链表

    常见操作

    - 插入节点(在头部、尾部或中间插入)

    在头部插入节点

    在尾部插入节点

    在中间插入节点(在指定位置后插入)

    - 删除节点(删除指定值的节点或指定位置的节点)

    删除指定值的节点

    删除指定位置的节点

    - 遍历链表

    四、总结


    蓝桥杯竞赛中,C语言是常用的编程语言之一。参赛者需要掌握一些常见的数据结构,以便高效地解决竞赛中的问题。以下是C语言中常见的几种数据结构及其基本操作的介绍。

    一、 数组(Array

    1、定义和初始化
    数组是一种线性数据结构,用于存储固定大小的相同类型元素。

    1. // 定义和初始化一个整型数组
    2. int arr[5] = {1, 2, 3, 4, 5};
    3. // 动态分配数组
    4. int *arr = (int *)malloc(5 * sizeof(int));

    2、访问和修改元素

    1. // 访问数组元素
    2. int value = arr[2]; // 获取第三个元素
    3. // 修改数组元素
    4. arr[2] = 10; // 将第三个元素修改为10

    3、常见操作


    - 遍历数组
    1. #include
    2. void traverseArray(int arr[], int size) {
    3. for (int i = 0; i < size; i++) {
    4. printf("%d ", arr[i]);
    5. }
    6. printf("\n");
    7. }
    8. int main() {
    9. int arr[] = {1, 2, 3, 4, 5};
    10. int size = sizeof(arr) / sizeof(arr[0]);
    11. traverseArray(arr, size);
    12. return 0;
    13. }

    - 查找元素
    线性查找
    1. #include <stdio.h>
    2. int linearSearch(int arr[], int size, int target) {
    3. for (int i = 0; i < size; i++) {
    4. if (arr[i] == target) {
    5. return i; // 返回目标元素的索引
    6. }
    7. }
    8. return -1; // 没有找到目标元素
    9. }
    10. int main() {
    11. int arr[] = {1, 2, 3, 4, 5};
    12. int size = sizeof(arr) / sizeof(arr[0]);
    13. int target = 3;
    14. int result = linearSearch(arr, size, target);
    15. if (result != -1) {
    16. printf("Element found at index %d\n", result);
    17. } else {
    18. printf("Element not found\n");
    19. }
    20. return 0;
    21. }
    二分查找(适用于有序数组)
    1. #include
    2. int binarySearch(int arr[], int size, int target) {
    3. int left = 0, right = size - 1;
    4. while (left <= right) {
    5. int mid = left + (right - left) / 2;
    6. if (arr[mid] == target) {
    7. return mid; // 找到目标元素
    8. }
    9. if (arr[mid] < target) {
    10. left = mid + 1; // 向右半部分查找
    11. } else {
    12. right = mid - 1; // 向左半部分查找
    13. }
    14. }
    15. return -1; // 没有找到目标元素
    16. }
    17. int main() {
    18. int arr[] = {1, 2, 3, 4, 5};
    19. int size = sizeof(arr) / sizeof(arr[0]);
    20. int target = 3;
    21. int result = binarySearch(arr, size, target);
    22. if (result != -1) {
    23. printf("Element found at index %d\n", result);
    24. } else {
    25. printf("Element not found\n");
    26. }
    27. return 0;
    28. }
    - 排序数组(如冒泡排序、快速排序等)
    冒泡排序
    1. #include <stdio.h>
    2. void bubbleSort(int arr[], int size) {
    3. for (int i = 0; i < size - 1; i++) {
    4. for (int j = 0; j < size - i - 1; j++) {
    5. if (arr[j] > arr[j + 1]) {
    6. // 交换元素
    7. int temp = arr[j];
    8. arr[j] = arr[j + 1];
    9. arr[j + 1] = temp;
    10. }
    11. }
    12. }
    13. }
    14. int main() {
    15. int arr[] = {5, 2, 9, 1, 5, 6};
    16. int size = sizeof(arr) / sizeof(arr[0]);
    17. bubbleSort(arr, size);
    18. for (int i = 0; i < size; i++) {
    19. printf("%d ", arr[i]);
    20. }
    21. printf("\n");
    22. return 0;
    23. }
    快速排序
    1. #include
    2. void swap(int* a, int* b) {
    3. int temp = *a;
    4. *a = *b;
    5. *b = temp;
    6. }
    7. int partition(int arr[], int low, int high) {
    8. int pivot = arr[high]; // 选择最后一个元素作为枢轴
    9. int i = (low - 1); // 较小元素的索引
    10. for (int j = low; j <= high - 1; j++) {
    11. // 如果当前元素小于或等于枢轴
    12. if (arr[j] <= pivot) {
    13. i++; // 增加较小元素的索引
    14. swap(&arr[i], &arr[j]);
    15. }
    16. }
    17. swap(&arr[i + 1], &arr[high]);
    18. return (i + 1);
    19. }
    20. void quickSort(int arr[], int low, int high) {
    21. if (low < high) {
    22. int pi = partition(arr, low, high);
    23. // 分别对枢轴元素左右两部分进行快速排序
    24. quickSort(arr, low, pi - 1);
    25. quickSort(arr, pi + 1, high);
    26. }
    27. }
    28. int main() {
    29. int arr[] = {10, 7, 8, 9, 1, 5};
    30. int size = sizeof(arr) / sizeof(arr[0]);
    31. quickSort(arr, 0, size - 1);
    32. for (int i = 0; i < size; i++) {
    33. printf("%d ", arr[i]);
    34. }
    35. printf("\n");
    36. return 0;
    37. }

    二、 链表(Linked List)

    1、定义节点结构
    链表是一种线性数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。

    1. // 定义链表节点结构
    2. struct Node {
    3.     int data;
    4.     struct Node *next;
    5. };

    2、创建和初始化链表

    1. // 创建一个新节点
    2. struct Node* createNode(int data) {
    3.     struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    4.     newNode->data = data;
    5.     newNode->next = NULL;
    6.     return newNode;
    7. }
    8. // 初始化链表
    9. struct Node* head = createNode(1);
    10. head->next = createNode(2);
    11. head->next->next = createNode(3);

    常见操作


    - 插入节点(在头部、尾部或中间插入)
    在头部插入节点
    1. void insertAtHead(struct Node** head, int data) {
    2. struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    3. newNode->data = data;
    4. newNode->next = *head;
    5. *head = newNode;
    6. }
    在尾部插入节点
    1. void insertAtTail(struct Node** head, int data) {
    2. struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    3. newNode->data = data;
    4. newNode->next = NULL;
    5. if (*head == NULL) {
    6. *head = newNode;
    7. return;
    8. }
    9. struct Node* temp = *head;
    10. while (temp->next != NULL) {
    11. temp = temp->next;
    12. }
    13. temp->next = newNode;
    14. }
    在中间插入节点(在指定位置后插入)
    1. void insertAfter(struct Node* prevNode, int data) {
    2. if (prevNode == NULL) {
    3. printf("Previous node cannot be NULL\n");
    4. return;
    5. }
    6. struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    7. newNode->data = data;
    8. newNode->next = prevNode->next;
    9. prevNode->next = newNode;
    10. }
    - 删除节点(删除指定值的节点或指定位置的节点)
    删除指定值的节点
    1. void deleteNodeByValue(struct Node** head, int key) {
    2. struct Node* temp = *head;
    3. struct Node* prev = NULL;
    4. // 如果头节点就是要删除的节点
    5. if (temp != NULL && temp->data == key) {
    6. *head = temp->next; // 改变头节点
    7. free(temp); // 释放旧头节点
    8. return;
    9. }
    10. // 搜索要删除的节点,保持前一个节点的指针
    11. while (temp != NULL && temp->data != key) {
    12. prev = temp;
    13. temp = temp->next;
    14. }
    15. // 如果没有找到要删除的节点
    16. if (temp == NULL) return;
    17. // 解除节点链接
    18. prev->next = temp->next;
    19. free(temp); // 释放内存
    20. }
    删除指定位置的节点
    1. void deleteNodeByPosition(struct Node** head, int position) {
    2. if (*head == NULL) return;
    3. struct Node* temp = *head;
    4. // 如果头节点需要被删除
    5. if (position == 0) {
    6. *head = temp->next; // 改变头节点
    7. free(temp); // 释放旧头节点
    8. return;
    9. }
    10. // 找到要删除的节点的前一个节点
    11. for (int i = 0; temp != NULL && i < position - 1; i++) {
    12. temp = temp->next;
    13. }
    14. // 如果位置超过链表长度
    15. if (temp == NULL || temp->next == NULL) return;
    16. // 节点temp->next是要删除的节点
    17. struct Node* next = temp->next->next;
    18. free(temp->next); // 释放内存
    19. temp->next = next; // 解除节点链接
    20. }
    - 遍历链表
    1. void traverseList(struct Node* head) {
    2. struct Node* temp = head;
    3. while (temp != NULL) {
    4. printf("%d -> ", temp->data);
    5. temp = temp->next;
    6. }
    7. printf("NULL\n");
    8. }

    三、栈(Stack)

    1、定义和初始化
    栈是一种后进先出(LIFO)的数据结构,可使用数组或链表实现。

    1. // 使用数组实现栈
    2. #define MAX 100
    3. struct Stack {
    4.     int top;
    5.     int items[MAX];
    6. };
    7. // 初始化栈
    8. void initStack(struct Stack* s) {
    9.     s->top = -1;
    10. }
    11. // 检查栈是否为空
    12. int isEmpty(struct Stack* s) {
    13.     return s->top == -1;
    14. }
    15. // 检查栈是否满
    16. int isFull(struct Stack* s) {
    17.     return s->top == MAX - 1;
    18. }

    2、 常见操作


    - 压栈(Push)
    1. void push(struct Stack* s, int item) {
    2.     if (isFull(s)) {
    3.         printf("Stack is full\n");
    4.         return;
    5.     }
    6.     s->items[++s->top] = item;
    7. }
    - 弹栈(Pop)
    1. int pop(struct Stack* s) {
    2.     if (isEmpty(s)) {
    3.         printf("Stack is empty\n");
    4.         return -1;
    5.     }
    6.     return s->items[s->top--];
    7. }
    - 获取栈顶元素(Peek)
    1. int peek(struct Stack* s) {
    2.     if (isEmpty(s)) {
    3.         printf("Stack is empty\n");
    4.         return -1;
    5.     }
    6.     return s->items[s->top];
    7. }

    四、 队列(Queue)

    1、定义和初始化
    队列是一种先进先出(FIFO)的数据结构,可使用数组或链表实现。

    1. // 使用数组实现队列
    2. #define MAX 100
    3. struct Queue {
    4.     int front, rear, size;
    5.     int items[MAX];
    6. };
    7. // 初始化队列
    8. void initQueue(struct Queue* q) {
    9.     q->front = 0;
    10.     q->rear = MAX - 1;
    11.     q->size = 0;
    12. }
    13. // 检查队列是否为空
    14. int isEmpty(struct Queue* q) {
    15.     return q->size == 0;
    16. }
    17. // 检查队列是否满
    18. int isFull(struct Queue* q) {
    19.     return q->size == MAX;
    20. }

    2、常见操作


    - 入队(Enqueue)
    1. void enqueue(struct Queue* q, int item) {
    2.     if (isFull(q)) {
    3.         printf("Queue is full\n");
    4.         return;
    5.     }
    6.     q->rear = (q->rear + 1) % MAX;
    7.     q->items[q->rear] = item;
    8.     q->size++;
    9. }
    - 出队(Dequeue)
    1. int dequeue(struct Queue* q) {
    2.     if (isEmpty(q)) {
    3.         printf("Queue is empty\n");
    4.         return -1;
    5.     }
    6.     int item = q->items[q->front];
    7.     q->front = (q->front + 1) % MAX;
    8.     q->size--;
    9.     return item;
    10. }
    - 获取队首元素(Front)
    1. int front(struct Queue* q) {
    2.     if (isEmpty(q)) {
    3.         printf("Queue is empty\n");
    4.         return -1;
    5.     }
    6.     return q->items[q->front];
    7. }

    五、树 (Tree)

    树是一种分层数据结构,由节点(Node)组成,每个节点包含一个值和指向子节点的指针。最常见的树类型是二叉树(Binary Tree),其中每个节点最多有两个子节点。

    1、二叉树节点结构定义
    1. #include
    2. #include
    3. // 定义二叉树节点结构
    4. struct TreeNode {
    5. int data;
    6. struct TreeNode* left;
    7. struct TreeNode* right;
    8. };
    2、插入节点

      二叉搜索树(Binary Search Tree, BST) 的插入函数为例。二叉搜索树是一种特殊的二叉树,其中每个节点的左子树包含的节点值都小于该节点的值,而右子树包含的节点值都大于该节点的值。

    插入节点的过程

    1. 检查根节点是否为空
      • 如果根节点为空,创建一个新的节点并将其作为根节点返回。
    2. 比较插入值与当前节点值
      • 如果插入值小于当前节点值,递归地在左子树中插入该值。
      • 如果插入值大于当前节点值,递归地在右子树中插入该值。
    1. // 插入节点函数
    2. struct TreeNode* insertNode(struct TreeNode* root, int data) {
    3. if (root == NULL) {
    4. struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    5. newNode->data = data;
    6. newNode->left = newNode->right = NULL;
    7. return newNode;
    8. }
    9. if (data < root->data) {
    10. root->left = insertNode(root->left, data);
    11. } else {
    12. root->right = insertNode(root->right, data);
    13. }
    14. return root;
    15. }
    3、遍历二叉树
    1. // 中序遍历函数
    2. void inorderTraversal(struct TreeNode* root) {
    3. if (root != NULL) {
    4. inorderTraversal(root->left);
    5. printf("%d ", root->data);
    6. inorderTraversal(root->right);
    7. }
    8. }

    六、图 (Graph)

    图是一种非线性数据结构,由节点(顶点)和连接这些节点的边组成。图可以是有向的(Directed)或无向的(Undirected)。

    邻接矩阵表示图

    1. #include
    2. #include
    3. #define MAX_VERTICES 5
    4. // 添加边的函数
    5. void addEdge(int graph[MAX_VERTICES][MAX_VERTICES], int u, int v) {
    6. graph[u][v] = 1;
    7. graph[v][u] = 1; // 如果是无向图
    8. }
    9. // 打印图的函数
    10. void printGraph(int graph[MAX_VERTICES][MAX_VERTICES]) {
    11. for (int i = 0; i < MAX_VERTICES; i++) {
    12. for (int j = 0; j < MAX_VERTICES; j++) {
    13. printf("%d ", graph[i][j]);
    14. }
    15. printf("\n");
    16. }
    17. }
    18. int main() {
    19. int graph[MAX_VERTICES][MAX_VERTICES] = {0};
    20. addEdge(graph, 0, 1);
    21. addEdge(graph, 0, 4);
    22. addEdge(graph, 1, 2);
    23. addEdge(graph, 1, 3);
    24. addEdge(graph, 1, 4);
    25. addEdge(graph, 2, 3);
    26. addEdge(graph, 3, 4);
    27. printGraph(graph);
    28. return 0;
    29. }

    七、哈希表 (Hash Table)

    哈希表是一种用于快速查找的数据结构,通过哈希函数将键映射到数组中的位置。

    1、哈希表节点结构定义

    1. #include
    2. #include
    3. #include
    4. #define TABLE_SIZE 10
    5. // 定义哈希表节点结构
    6. struct HashNode {
    7. int key;
    8. int value;
    9. struct HashNode* next;
    10. };
    11. // 定义哈希表结构
    12. struct HashTable {
    13. struct HashNode* table[TABLE_SIZE];
    14. };

    2、哈希函数

    1. // 哈希函数
    2. int hashFunction(int key) {
    3. return key % TABLE_SIZE;
    4. }

    3、插入键值对

    1. // 插入键值对的函数
    2. void insert(struct HashTable* hashTable, int key, int value) {
    3. int hashIndex = hashFunction(key);
    4. struct HashNode* newNode = (struct HashNode*)malloc(sizeof(struct HashNode));
    5. newNode->key = key;
    6. newNode->value = value;
    7. newNode->next = hashTable->table[hashIndex];
    8. hashTable->table[hashIndex] = newNode;
    9. }

    4、查找键值对

    1. // 查找键值对的函数
    2. int search(struct HashTable* hashTable, int key) {
    3. int hashIndex = hashFunction(key);
    4. struct HashNode* node = hashTable->table[hashIndex];
    5. while (node != NULL) {
    6. if (node->key == key) {
    7. return node->value;
    8. }
    9. node = node->next;
    10. }
    11. return -1; // 未找到键
    12. }

    总结

         掌握这些常见的数据结构及其基本操作是参加蓝桥杯竞赛的基础。通过练习和理解这些数据结构,咱将能够更高效地解决竞赛中的各种编程问题。希望这些介绍对你有所帮助!如果你有任何具体问题或需要进一步的帮助,请随时告诉我。

  • 相关阅读:
    九、SpringMVC(3)
    Python课程设计之学生信息管理系统
    算法面试-深度学习基础面试题整理-AIGC相关(2023.9.01)
    软件工程理论与实践 (吕云翔) 第八章 软件体系结构与设计模式课后习题及其答案解析
    SQL必需掌握的100个重要知识点:更新和删除数据
    淘宝战场分离,淘宝商家跻身抖音电商,是自掘坟墓还是另有他法?
    Llama 3 开源了「GitHub 热点速览」
    HTML5学习笔记(一)
    linux使用vi/vim进行多行注释和取消
    LeetCode_贪心算法_困难_630.课程表 III
  • 原文地址:https://blog.csdn.net/aaaa_hsjsueu/article/details/139417715