数据结构与算法

简介

数据结构

数据结构(Data Structure)是计算机中存储、组织和管理数据的方式,旨在高效地访问和修改数据。

它定义了数据元素之间的逻辑关系、操作(如增删查改)以及如何在内存中物理存储。

算法(Algorithm)

算法是实现的、解决问题的步骤逻辑,强调效率与正确性。

它是编写高性能程序的基础,通常通过函数、循环和数据结构组合实现。

内容:

顺序查找

二分查找

排序:冒泡、快速排序

数据结构

  • 基本概念

    • 物理结构
    • 逻辑结构
  • 操作数据的方法(增、删、改、查看)

    • 增加数据
    • 删除数据
    • 修改数据
    • 查看数据
    • 初始化数据
    • 销毁数据

内容:

  • 线性表
  • 动态数组
  • 链表
  • 队列

顺序存储(数组)

写一个程序,用来存储学生的成绩。

操作方法:

  1. 初始化数据结构
  2. 添加学生成绩
  3. 打印所有的学生成绩
  4. 修改第 i 个学生的成绩。
  5. 删除某个位置的学生成绩。
  6. 销毁数据结构.
  7. 在 pos 之前的位置插入学生的成绩

数据结构

复制代码
struct stu_score {
     int data[100];  // 用来保存学生的成绩数据
     int count; // 用来记录学生的个数。
}

初始代码

复制代码
#include <stdio.h>

struct stu_score {
     int data[100];  // 用来保存学生的成绩数据
     int count; // 用来记录学生的个数。
};
// 1.  初始化数据结构,成功返回1,不成功返回0
int init_data(struct stu_score *stu) { }
// 2.  添加学生成绩,成功返回1,不成功返回0
int append_data(struct stu_score * stu, int score) {}
// 3.  打印所有的学生成绩
void list_all_data(const struct stu_score * stu) {}
// 4.  修改第 i 个学生的成绩。
int modify_data(struct stu_score * stu, int pos, int score) {}
// 5.  删除某个位置的学生成绩。
int remove_data(struct stu_score * stu, int pos) {}
// 6.  销毁数据结构.
int destroy_data(struct stu_score * stu) {}
// 7.  在 pos 之前的位置插入学生的成绩
int insert_data(struct stu_score * stu, int pos, int score){}

int main(int argc, char * argv[]) {
 struct stu_score stu; // 定义一个顺序存储数据的变量
 return 0;
}

最终代码:

复制代码
#include <stdio.h>

struct stu_score {
     int data[100];  // 用来保存学生的成绩数据
     int count; // 用来记录学生的个数。
};
// 1.  初始化数据结构,成功返回1,不成功返回0
int init_data(struct stu_score *stu) {
 stu->count = 0;   // (*stu).count = 0;
 return 1;
}
// 2.  添加学生成绩,成功返回1,不成功返回0
int append_data(struct stu_score * stu, int score) {
 if (stu->count >= 
   sizeof(stu->data)/sizeof(stu->data[0]) )
  return 0;
 stu->data[stu->count] = score;
 stu->count++;
 return 1;
}
// 3.  打印所有的学生成绩
void list_all_data(const struct stu_score * stu) {
 printf("学生个数:%d\n", stu->count);
 for (int i = 0; i < stu->count; i++) {
  printf("%d ", stu->data[i]);
 }
 printf("\n");
}
// 4.  修改第 i 个学生的成绩。pos 从 0 开始
int modify_data(struct stu_score * stu, int pos, int score){
 if (pos < 0 || pos >= stu->count)
  return 0;
    stu->data[pos] = score;
 return 1;

}
// 5.  删除某个位置的学生成绩。
int remove_data(struct stu_score * stu, int pos) {
 if (pos < 0 || pos >= stu->count)
  return 0;
 for (int i = pos; i < stu->count -1; i++) {
  stu->data[i] = stu->data[i+1];
 }
 stu->count--;
 return 1;
}
// 6.  销毁数据结构.
int destroy_data(struct stu_score * stu) {
 return 1;
}
// 7.  在 pos 之前的位置插入学生的成绩
int insert_data(struct stu_score * stu, int pos, int score){
 if (pos < 0 || pos > stu->count)
  return 0;
 for (int i = stu->count - 1; i >= pos; i--) {
   stu->data[i+1] = stu->data[i];
 }
 stu->data[pos] = score;
 stu->count++;
}

int main(int argc, char * argv[]) {
 struct stu_score stu; // 定义一个顺序存储数据的变量
 int ret; // 此变量用来保存函数的返回值
 ret = init_data(&stu);
 printf("init_data: ret:%d\n", ret);
 ret = append_data(&stu, 100);
 printf("append_data: ret:%d\n", ret);
 ret = append_data(&stu, 90);
 ret = append_data(&stu, 80);
 list_all_data(&stu);  // 打印列表
 ret = modify_data(&stu, 2,99);//将第三个学生的成绩改成99
 printf("modify_data: ret:%d\n", ret);
 list_all_data(&stu);  // 打印列表
 ret = remove_data(&stu, 3);
 printf("remove_data: ret:%d\n", ret);
 list_all_data(&stu);  // 打印列表
 ret = insert_data(&stu, 1, 60);
 printf("insert_data: ret:%d\n", ret);
 list_all_data(&stu);  // 打印列表
 return 0;
}

时间复杂度:

算法的时间复杂度是衡量算法运行时间随输入规模增长而变化的度量,通常用大O符号(O-notation)表示。它描述的是在最坏情况下,算法执行的基本操作次数与输入规模之间的关系,忽略常数项和低阶项,专注于增长趋势。

输入规模(n)

按增长速度从低到高排序:

  1. 常数时间
    O(1):操作次数与输入规模无关(如数组随机访问)。
  2. 对数时间
    O(log⁡n):常见于分治算法(如二分查找)。
  3. 线性时间
    O(n):操作次数与输入规模成正比(如遍历数组)。
  4. 线性对数时间
    O(nlog⁡n):常见于高效排序算法(归并排序)。
  5. 平方时间
    O(n2):常见于双重循环(如冒泡排序)。
  6. 指数时间
    O(2n) 或 O (n!):常见于暴力搜索。

动态数组

动态数组也是顺序存储结构,动态数组使用动态分配的内存存储数据,在数据已经满的情况下,分配更多的内存来存储数据。

动态数组示例

复制代码
#include <stdio.h>
#include <stdlib.h>

struct stu_score {
 int * data;  // 用来保存学生的成绩数据的指针
 int count; // 用来记录学生的个数。
 int max_count;  // 用来记录当前内存能存储的最大数据
};
// 0. 扩大动态数组,将内存长度扩大一倍,数据由旧内存复制到新内存
int double_data_volume(struct stu_score *pstu) {
 int * temp = (int*)malloc(
   2 * sizeof(int) * pstu->max_count);
 if (!temp)
  return 0;
 for (int i = 0; i < pstu->count; i++) {
  temp[i] = pstu->data[i];
 }
 free(pstu->data); // 释放旧内存
 pstu->data = temp; // 指向新内存
 temp = NULL;
 pstu->max_count *= 2;
 return 1;
}
// 1.  初始化数据结构,成功返回1,不成功返回0
int init_data(struct stu_score *stu) {
 stu->count = 0;   // (*stu).count = 0;
 stu->max_count = 5;
 stu->data = (int*)malloc(sizeof(stu->data[0]) * 5); 
 if (stu->data == NULL)
  return 0;
 return 1;
}
// 2.  添加学生成绩,成功返回1,不成功返回0
int append_data(struct stu_score * pstu, int score) {
 if (pstu->count >= pstu->max_count) 
  if (!double_data_volume(pstu))
   return 0;
 pstu->data[pstu->count] = score;
 pstu->count++;
 return 1;
}
// 3.  打印所有的学生成绩
void list_all_data(const struct stu_score * stu) {
 printf("学生个数:%d\n", stu->count);
 for (int i = 0; i < stu->count; i++) {
  printf("%d ", stu->data[i]);
 }
 printf("\n");
}
// 4.  修改第 i 个学生的成绩。pos 从 0 开始
int modify_data(struct stu_score * stu, int pos, int score){
 if (pos < 0 || pos >= stu->count)
  return 0;
    stu->data[pos] = score;
 return 1;

}
// 5.  删除某个位置的学生成绩。
int remove_data(struct stu_score * stu, int pos) {
 if (pos < 0 || pos >= stu->count)
  return 0;
 for (int i = pos; i < stu->count -1; i++) {
  stu->data[i] = stu->data[i+1];
 }
 stu->count--;
 return 1;
}
// 6.  销毁数据结构.
int destroy_data(struct stu_score * pstu) {
 free(pstu->data);
 pstu->data = NULL;
 pstu->count = 0;
 pstu->max_count = 0;
 return 1;
}
// 7.  在 pos 之前的位置插入学生的成绩
int insert_data(struct stu_score * pstu, int pos, int score){
 if (pos < 0 || pos > pstu->count)
  return 0;
 if (pstu->count >= pstu->max_count) 
  if (!double_data_volume(pstu))
   return 0;
 for (int i = pstu->count - 1; i >= pos; i--) {
   pstu->data[i+1] = pstu->data[i];
 }
 pstu->data[pos] = score;
 pstu->count++;
 return 1;
}

int main(int argc, char * argv[]) {
 struct stu_score stu; // 定义一个顺序存储数据的变量
 int ret; // 此变量用来保存函数的返回值
 ret = init_data(&stu);
 printf("init_data: ret:%d\n", ret);
 for (int i = 10; i <= 50; i+= 10)
  append_data(&stu, i);
 list_all_data(&stu);  // 打印列表
// 	ret = modify_data(&stu, 2,99);//将第三个学生的成绩改成99
// 	printf("modify_data: ret:%d\n", ret);
// 	list_all_data(&stu);  // 打印列表
// 	ret = remove_data(&stu, 3);
// 	printf("remove_data: ret:%d\n", ret);
// 	list_all_data(&stu);  // 打印列表
  ret = insert_data(&stu, 1, 60);
  printf("insert_data: ret:%d\n", ret);
  list_all_data(&stu);  // 打印列表
 return 0;
}

栈是一种先进后出的数据结构。犹如弹夹一样,最先压进的子弹最后才被打出

栈的基本操作

  • 初始化栈
  • 清空栈
  • 判断栈空
  • 判断栈满
  • 获取栈顶元素
  • 获取栈元素个数
  • 入栈
  • 出栈

使用顺序存储结构来实现栈

复制代码
struct stack {
    int data[100];
    int top;
}

数据结构和算法的网站:Data Structure Visualization

框架代码

复制代码
#include <stdio.h>

struct stack {
     int data[20];  // 用来保存数据
     int top; // 用来记录栈顶的位置
};
// 初始化栈
void stack_init(struct stack * pstk) { }
// 清空栈
void stack_clear(struct stack * pstk) { }
// 判断栈空, 栈为空返回 1, 否则返回0
int stack_is_empty(struct stack * pstk) { }
// 判断栈满 栈为满返回 1, 否则返回0
int stack_is_full(struct stack * pstk) { }
// 获取栈顶元素,成功返回1,数据放入pvalue指向的变量,失败返回0
int stack_top_value(struct stack * pstk, int * pvalue) { }
// 获取栈元素个数
int stack_get_value_count(struct stack *pstk) {}
// 入栈:成功返回1,失败返回0
int stack_push(struct stack *pstk, int value) {}
// 出栈:成功返回1,数据放入pvalue指向的变量
int stack_pop(struct stack * pstk, int * pvalue) { }

int main(int argc, char * argv[]) {
 struct stack stk; // 定义一个栈
 return 0;
}

最终代码

复制代码
#include <stdio.h>

struct stack {
     int data[20];  // 用来保存数据
     int top; // 用来记录栈顶的位置
};
// 初始化栈
void stack_init(struct stack * pstk) {
 pstk->top = 0;
}
// 清空栈
void stack_clear(struct stack * pstk) {
 stack_init(pstk);
}
// 判断栈空, 栈为空返回 1, 否则返回0
int stack_is_empty(struct stack * pstk) {
 return pstk->top == 0;
}
// 判断栈满 栈为满返回 1, 否则返回0
int stack_is_full(struct stack * pstk) {
 return pstk->top == sizeof(pstk->data) / sizeof(pstk->data[0]);
}
// 获取栈顶元素,成功返回1,数据放入pvalue指向的变量,失败返回0
int stack_top_value(struct stack * pstk, int * pvalue) {
 if (pstk->top == 0)
  return 0;
 *pvalue = pstk->data[pstk->top-1];
 return 1;
}
// 获取栈元素个数
int stack_get_value_count(struct stack *pstk) {
 return pstk->top;
}
// 入栈:成功返回1,失败返回0
int stack_push(struct stack *pstk, int value) {
 if (stack_is_full(pstk))
     return 0;
 pstk->data[pstk->top] = value;
 pstk->top++;
}
// 出栈:成功返回1,数据放入pvalue指向的变量
int stack_pop(struct stack * pstk, int * pvalue) {
 if (stack_is_empty(pstk))
  return 0;
 pstk->top--;
 *pvalue = pstk->data[pstk->top];
 return 1;
}

int main(int argc, char * argv[]) {
 struct stack stk; // 定义一个栈
 if (stk.top == 0) 
 return 0;
}

栈的分类标准定义

栈的分类主要基于两个相互独立的维度:

  1. 增长方向 (Growth Direction): 栈在内存中扩展(压栈)和收缩(弹栈)的方向。

  2. 栈指针指向 (Stack Pointer Status): 栈顶指针 (SP - Stack Pointer) 当前指向的位置是否包含有效的栈数据。

维度一:增长方向

  • 增栈 (Ascending Stack):

    • 定义: 当向栈中压入 (Push) 数据时,栈顶指针 SP 向内存地址增加的方向移动 (值变大)。当从栈中弹出 (Pop) 数据时,SP 向内存地址减小的方向移动(值变小)。

    • 核心特征: 压栈使 SP 增加,弹栈使 SP 减少

    • 内存布局: 栈底位于较低内存地址,栈顶向较高内存地址增长。

  • 减栈 (Descending Stack):

    • 定义: 当向栈中压入 (Push) 数据时,栈顶指针 SP 向内存地址减小的方向移动 (值变小)。当从栈中弹出 (Pop) 数据时,SP 向内存地址增加的方向移动(值变大)。

    • 核心特征: 压栈使 SP 减少,弹栈使 SP 增加

    • 内存布局: 栈底位于较高内存地址,栈顶向较低内存地址增长(这是最常见的设计,如 x86, ARM 的默认模式)。

维度二:栈指针指向

  • 满栈 (Full Stack):

    • 定义: 栈顶指针 SP 始终指向栈中最后一个被压入的有效数据项

    • 核心特征: SP 指向的位置有数据

    • 操作顺序:

      • 压栈 (Push): 必须先移动 SP 到下一个可用位置,然后将数据存入 SP 指向的新位置。

      • 弹栈 (Pop): 必须先读取 SP 指向位置的数据,然后移动 SP 释放该位置。

  • 空栈 (Empty Stack):

    • 定义: 栈顶指针 SP 始终指向栈顶元素(最后一个有效数据项)的下一个可用(空)位置

    • 核心特征: SP 指向的位置没有数据(是下一个可用位置)

    • 操作顺序:

      • 压栈 (Push): 必须先将数据存入 SP 当前指向的位置,然后移动 SP 指向下一个可用位置。

      • 弹栈 (Pop): 必须先移动 SP 指向上一个数据项的位置,然后读取该位置的数据。

组合与说明

这两个维度是正交的,可以组合形成四种类型的栈:

  1. 满增栈 (Full Ascending - FA): SP 指向栈顶数据,压栈时 SP 增大,弹栈时 SP 减小。

  2. 空增栈 (Empty Ascending - EA): SP 指向栈顶下一个空位,压栈时存入数据后 SP 增大,弹栈时 SP 减小后读取数据。

  3. 满减栈 (Full Descending - FD): SP 指向栈顶数据,压栈时 SP 减小,弹栈时 SP 增大。(这是最常见的组合,例如 x86 架构、ARM 的默认模式)。

  4. 空减栈 (Empty Descending - ED): SP 指向栈顶下一个空位,压栈时存入数据后 SP 减小,弹栈时 SP 增大后读取数据。

关键记忆点

  • 增/减:压栈操作 时 SP 是增加 (Ascending) 还是减少 (Descending)

  • 满/空: 看 SP 当前指向的位置 是否有数据 (Full) 还是无数据/下一个空位 (Empty)

  • 操作顺序: 满栈操作需要 先移指针再操作数据 (压栈)或 先操作数据再移指针 (弹栈)。空栈操作需要 先操作数据再移指针 (压栈)或 先移指针再操作数据(弹栈)。

总结表格

特性 增栈 (Ascending) 减栈 (Descending)
压栈方向 SP 增加 (向高地址) SP 减少 (向低地址)
弹栈方向 SP 减少 (向低地址) SP 增加 (向高地址)
栈底位置 低内存地址 高内存地址
栈增长方向 向高内存地址 向低内存地址
特性 满栈 (Full) 空栈 (Empty)
SP 指向 最后一个有效数据项 (有数据) 下一个可用空位 (无数据)
压栈操作顺序 1. 移动 SP 2. 存入数据 1. 存入数据 2. 移动 SP
弹栈操作顺序 1. 读取数据 2. 移动 SP 1. 移动 SP 2. 读取数据

队列

队列是一种先进先出(FIFO,First In First Out)的线性数据结构。

队列的物理结构分为顺序存储和链式存储两种。

队列的操作

  1. 初始化队列

  2. 入队

  3. 出队

  4. 队列空判断

  5. 队列满判断

  6. 队列内数据元素的个数

  7. 销毁队列

    #include <stdio.h>

    struct queue {
    int data[100]; // 用来保存数据
    int tail; // 数据个数。
    };
    // 1. 初始化队列
    void queue_init(struct queue * pq) { }
    // 4. 队列空判断, 空返回1, 否则返回0
    int queue_is_empty(struct queue * pq) { }
    // 5. 队列满判断, 满返回1, 否则返回0
    int queue_is_full(struct queue * pq) { }
    // 2. 入队, 成功返回1 ,失败返回0
    int queue_enqueue(struct queue *pq, int value) {}
    // 3. 出队, 成功返回1 ,失败返回0
    int queue_dequeue(struct queue pq, int pvalue) {}
    // 6. 对列内数据元素的个数
    int queue_get_data_count(struct queue
    pq) { }
    // 7. 销毁队列
    void queue_destroy(struct queue
    pq) { }

    int main(int argc, char * argv[]) {
    struct queue myqueue;
    return 0;
    }

最终实现

复制代码
#include <stdio.h>

struct queue {
     int data[100];  // 用来保存数据
     int tail; // 数据个数。
};
// 1.  初始化队列
void queue_init(struct queue * pq) {
 pq->tail = 0;
}
// 2.  队列空判断, 空返回1, 否则返回0
int queue_is_empty(struct queue * pq) {
    return 0 == pq->tail;
}
// 3.  队列满判断, 满返回1, 否则返回0
int queue_is_full(struct queue * pq) {
 return sizeof(pq->data)/sizeof(pq->data[0])==pq->tail; 
}
// 4.  入队, 成功返回1 ,失败返回0
int queue_enqueue(struct queue *pq, int value) {
 if (queue_is_full(pq))
  return 0;
 pq->data[pq->tail] = value; 
 pq->tail ++;
    return 1;
} 
// 5.  出队, 成功返回1 ,失败返回0
int queue_dequeue(struct queue *pq, int *pvalue) {
 if (queue_is_empty(pq))
  return 0;
 *pvalue = pq->data[0];

 // 向前移动数据
 for (int i = 0; i < pq->tail -1; i++) {
  pq->data[i] = pq->data[i+1];
 }
 pq->tail--;
 return 1;
} 
// 6.  队列内数据元素的个数
int queue_get_data_count(struct queue*pq) {
 return pq->tail;
}
// 7.  销毁队列
void queue_destroy(struct queue*pq) {
 pq->tail = 0;
}

环形队列

什么是环形队列,改进顺序存储的算法。用两个变量或指针分别指向头和尾部。通过算法降低入队和出队的时间复杂度的队列。

约定:头和尾重合即为空。否则尾非空。

实现结构

复制代码
struct queue {
     int data[20];  // 用来保存数据
     int head; // 队列头位置索引。
     int tail; // 队列尾位置索引。
};

示例代码

复制代码
// 写一个程序,实现队列的基本操作
// 1.  初始化队列
// 2.  队列空判断
// 3.  队列满判断
// 4.  入队
// 5.  出对
// 6.  对列内数据元素的个数
// 7.  销毁队列
#include <stdio.h>

#define QUEUE_SIZE 20  // 定义队列的最大容量

// 队列结构体定义
struct queue {
    int data[QUEUE_SIZE];  // 存储队列元素的数组
    int head;              // 队列头指针,指向队首元素
    int tail;              // 队列尾指针,指向下一个入队位置
};

// 1. 初始化队列
void queue_init(struct queue *pq) {
    // 将头指针和尾指针都设置为0,表示空队列
    pq->head = pq->tail = 0;
}

// 2. 判断队列是否为空
int queue_is_empty(struct queue *pq) {
    // 当头指针和尾指针相等时,队列为空
    return pq->head == pq->tail;
}

// 3. 判断队列是否已满
int queue_is_full(struct queue *pq) {
    // 计算尾指针的下一个位置(考虑循环队列)
    int next_tail = (pq->tail + 1) % QUEUE_SIZE;
    // 当下一个尾指针位置等于头指针时,队列已满
    return next_tail == pq->head;
}

// 4. 入队操作
int queue_enqueue(struct queue *pq, int value) {
    // 检查队列是否已满
    if (queue_is_full(pq))
        return 0;  // 队列已满,入队失败
    
    // 将值存入尾指针位置
    pq->data[pq->tail] = value;
    // 尾指针向前移动一位(考虑循环队列)
    pq->tail = (pq->tail + 1) % QUEUE_SIZE;
    return 1;  // 入队成功
}

// 5. 出队操作
int queue_dequeue(struct queue *pq, int *pvalue) {
    // 检查队列是否为空
    if (queue_is_empty(pq))
        return 0;  // 队列为空,出队失败
    
    // 从头指针位置取出值
    *pvalue = pq->data[pq->head];
    // 头指针向前移动一位(考虑循环队列)
    pq->head = (pq->head + 1) % QUEUE_SIZE;
    return 1;  // 出队成功
}

// 6. 获取队列中元素的数量
int queue_get_data_count(struct queue *pq) {
    if (pq->tail >= pq->head) {
        // 当尾指针在头指针之后(没有环绕)
        return pq->tail - pq->head;
    } else {
        // 当尾指针在头指针之前(发生环绕)
        return QUEUE_SIZE - (pq->head - pq->tail);
    }
}

// 7. 销毁队列
void queue_destroy(struct queue *pq) {
    // 重置头指针和尾指针,清空队列
    pq->head = pq->tail = 0;
}

// 打印队列状态信息
void print_queue_status(struct queue *pq) {
    printf("队列状态: ");
    printf("头=%d, 尾=%d, 元素数=%d, ", pq->head, pq->tail, queue_get_data_count(pq));
    printf(queue_is_empty(pq) ? "空" : "非空");
    printf(queue_is_full(pq) ? " 满\n" : "\n");
}

// 打印队列内容
void print_queue_content(struct queue *pq) {
    printf("队列内容: [");
    
    if (!queue_is_empty(pq)) {
        // 从头指针开始遍历
        int i = pq->head;
        do {
            // 打印当前元素
            printf("%d", pq->data[i]);
            // 移动到下一个位置(考虑循环队列)
            i = (i + 1) % QUEUE_SIZE;
            // 如果不是最后一个元素,添加分隔符
            if (i != pq->tail) printf(", ");
        } while (i != pq->tail);  // 遍历到尾指针位置结束
    }
    
    printf("]\n\n");
}

int main() {
    struct queue my_queue;  // 声明队列实例
    int value;              // 用于存储出队值
    
    /*** 测试1: 初始化队列 ***/
    queue_init(&my_queue);
    printf("=== 测试1: 初始化队列后 ===\n");
    print_queue_status(&my_queue);
    
    /*** 测试2: 入队操作 ***/
    printf("=== 测试2: 入队10个元素(1-10) ===\n");
    for (int i = 1; i <= 10; i++) {
        if (queue_enqueue(&my_queue, i)) {
            printf("入队: %d\n", i);
        } else {
            printf("入队失败: %d\n", i);
        }
    }
    print_queue_status(&my_queue);
    print_queue_content(&my_queue);
    
    /*** 测试3: 出队操作 ***/
    printf("=== 测试3: 出队5个元素 ===\n");
    for (int i = 0; i < 5; i++) {
        if (queue_dequeue(&my_queue, &value)) {
            printf("出队: %d\n", value);
        } else {
            printf("出队失败\n");
        }
    }
    print_queue_status(&my_queue);
    print_queue_content(&my_queue);
    
    /*** 测试4: 队列满测试 ***/
    printf("=== 测试4: 尝试填满队列 ===\n");
    for (int i = 11; i <= 30; i++) {
        if (queue_enqueue(&my_queue, i)) {
            printf("入队: %d\n", i);
        } else {
            printf("队列已满! 无法添加元素: %d\n", i);
            break;
        }
    }
    print_queue_status(&my_queue);
    print_queue_content(&my_queue);
    
    /*** 测试5: 清空队列 ***/
    printf("=== 测试5: 清空队列 ===\n");
    while (queue_dequeue(&my_queue, &value)) {
        printf("出队: %d\n", value);
    }
    print_queue_status(&my_queue);
    print_queue_content(&my_queue);
    
    /*** 测试6: 空队列出队测试 ***/
    printf("=== 测试6: 尝试从空队列出队 ===\n");
    if (queue_dequeue(&my_queue, &value)) {
        printf("出队: %d\n", value);
    } else {
        printf("无法出队 - 队列为空!\n");
    }
    print_queue_status(&my_queue);
    
    /*** 测试7: 队列循环特性测试 ***/
    printf("=== 测试7: 测试队列循环特性 ===\n");
    for (int i = 1; i <= 15; i++) {
        // 入队操作
        if (queue_enqueue(&my_queue, i * 10)) {
            printf("入队: %d\n", i * 10);
        } else {
            printf("入队失败: %d\n", i * 10);
        }
        
        // 每入队5个元素后出队1个
        if (i % 5 == 0) {
            if (queue_dequeue(&my_queue, &value)) {
                printf("出队: %d\n", value);
            } else {
                printf("出队失败\n");
            }
        }
    }
    print_queue_status(&my_queue);
    print_queue_content(&my_queue);
    
    /*** 测试8: 销毁队列 ***/
    printf("=== 测试8: 销毁队列 ===\n");
    queue_destroy(&my_queue);
    print_queue_status(&my_queue);
    
    return 0;
}
相关推荐
HW-BASE3 小时前
《C语言》指针练习题--1
c语言·开发语言·单片机·算法·c
遇见尚硅谷4 小时前
C语言:20250805学习(文件预处理)
服务器·c语言·学习
max5006004 小时前
深度学习的视觉惯性里程计(VIO)算法优化实践
人工智能·深度学习·算法
岁忧4 小时前
(nice!!!)(LeetCode 每日一题) 3363. 最多可收集的水果数目 (深度优先搜索dfs)
java·c++·算法·leetcode·go·深度优先
shenghaide_jiahu6 小时前
数学建模——粒子群算法
算法·数学建模
小杨爱搞嵌入式6 小时前
【STM32】GPIO的输入输出
c语言·笔记·stm32·单片机·学习
无规则ai6 小时前
动手学深度学习(pytorch版):第一章节——引言
人工智能·pytorch·深度学习·算法·机器学习
WeiJingYu.7 小时前
机器学习——随机森林
算法·随机森林·机器学习
丶小鱼丶8 小时前
二叉树算法之【中序遍历】
java·算法