当前位置: 首页 > news >正文

数据结构小白必看:手把手教你用C语言实现PTA题库中的经典算法

数据结构小白必看:手把手教你用C语言实现PTA题库中的经典算法

第一次接触数据结构时,看着课本上那些抽象的概念和复杂的图示,我完全摸不着头脑。直到在PTA题库里反复练习那些经典算法,才真正理解了数据结构的精髓。这篇文章将带你用最接地气的方式,从零开始实现那些让无数初学者头疼的数据结构算法。

1. 顺序表:数据结构的入门基石

顺序表就像一排连续的储物柜,每个格子都有固定编号。在C语言中,我们用数组来实现这种线性结构。先来看一个最简单的例子——顺序查找:

int sequentialSearch(int arr[], int size, int target) { for (int i = 0; i < size; i++) { if (arr[i] == target) { return i; // 找到返回索引 } } return -1; // 未找到 }

顺序表的插入操作需要特别注意元素的后移:

#define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int length; } SeqList; int insert(SeqList *L, int index, int value) { if (L->length == MAX_SIZE || index < 0 || index > L->length) { return 0; // 插入失败 } for (int i = L->length; i > index; i--) { L->data[i] = L->data[i-1]; // 元素后移 } L->data[index] = value; L->length++; return 1; // 插入成功 }

顺序表操作要点

  • 插入/删除时间复杂度为O(n)
  • 随机访问时间复杂度为O(1)
  • 适合元素数量固定、查询频繁的场景

2. 链表:灵活的动态数据结构

当我们需要频繁插入删除时,链表就派上用场了。单链表的基本结构如下:

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

头插法创建链表是PTA常考题型:

ListNode* createListHead(int arr[], int n) { ListNode *head = (ListNode*)malloc(sizeof(ListNode)); head->next = NULL; for (int i = 0; i < n; i++) { ListNode *node = (ListNode*)malloc(sizeof(ListNode)); node->data = arr[i]; node->next = head->next; head->next = node; } return head; }

链表删除操作要特别注意指针的修改顺序:

int deleteNode(ListNode *head, int index) { ListNode *p = head; int i = 0; while (p->next && i < index) { p = p->next; i++; } if (!p->next) return 0; // 删除失败 ListNode *temp = p->next; p->next = temp->next; free(temp); return 1; // 删除成功 }

提示:链表操作最容易出现内存泄漏,记得每次删除节点后都要free

3. 栈与队列:受限的线性表

栈是后进先出(LIFO)的结构,十进制转二进制是栈的经典应用:

#define STACK_SIZE 100 int stack[STACK_SIZE]; int top = -1; void push(int x) { if (top == STACK_SIZE - 1) return; stack[++top] = x; } int pop() { if (top == -1) return -1; return stack[top--]; } void decimalToBinary(int num) { while (num > 0) { push(num % 2); num /= 2; } while (top != -1) { printf("%d", pop()); } }

循环队列解决假溢出问题:

#define QUEUE_SIZE 5 typedef struct { int data[QUEUE_SIZE]; int front, rear; } CircularQueue; void initQueue(CircularQueue *q) { q->front = q->rear = 0; } int enQueue(CircularQueue *q, int x) { if ((q->rear + 1) % QUEUE_SIZE == q->front) return 0; // 队满 q->data[q->rear] = x; q->rear = (q->rear + 1) % QUEUE_SIZE; return 1; }

4. 二叉树:递归的艺术

二叉树遍历是理解递归的最佳案例。先序遍历的递归实现:

typedef struct TreeNode { char data; struct TreeNode *left, *right; } TreeNode; void preOrder(TreeNode *root) { if (root) { printf("%c ", root->data); preOrder(root->left); preOrder(root->right); } }

计算二叉树高度展示递归的威力:

int treeHeight(TreeNode *root) { if (!root) return 0; int left = treeHeight(root->left); int right = treeHeight(root->right); return (left > right ? left : right) + 1; }

二叉树操作要点

  • 递归终止条件必须明确
  • 先处理当前节点,再递归处理子树
  • 时间复杂度通常为O(n)

5. 查找算法:从暴力到优雅

顺序查找简单直接,但效率低下:

int seqSearch(int arr[], int n, int key) { for (int i = 0; i < n; i++) { if (arr[i] == key) return i; } return -1; }

二分查找要求数组有序,但效率极高:

int binarySearch(int arr[], int n, int key) { int left = 0, right = n - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == key) return mid; else if (arr[mid] < key) left = mid + 1; else right = mid - 1; } return -1; }

注意:二分查找的数组必须是有序的,否则结果不可预测

在实际刷PTA题库时,我发现最常犯的错误就是边界条件处理不当。比如二分查找中的left <= right判断,或者链表操作时的空指针检查。建议每个算法都先用小数据测试各种边界情况。

http://www.jsqmd.com/news/641771/

相关文章:

  • CSDN干货:小白程序员轻松掌握大模型接口自动化,收藏必备!
  • 如何永久保存微信聊天记录?免费开源WeChatMsg终极解决方案
  • AgentScope Spring AI Alibaba 大模型应用:小白程序员必备的多智能体实践指南(含收藏)
  • 通过 AGENTS.md、CLAUDE.md、SOUL.md和 MEMORY.md等文件来构建 Agent Harness避坑
  • 保姆级避坑指南:在Windows上用Docker+Unity 2022搭建ROS2 Jazzy仿真环境(含Panda机械臂)
  • Python编程:happybase读写HBase数据库
  • MedGemma X-Ray实战体验:上传X光片,3秒获取专业影像解读报告
  • WOFOST作物生长周期与PCSE农业生产模型实践技术应用
  • 如何永久珍藏微信聊天记忆?WeChatMsg免费工具完整指南
  • **发散创新:基于Python的实时反作弊检测系统设计与实现**在现代在线游戏和平台中
  • 警惕!多模态数据中的“幽灵模态”正在 silently 毒化你的模型:3大检测信号+1小时应急响应流程
  • 服务器如何防范爬虫攻击?
  • 告别查重与 AIGC 双重焦虑:虎贲等考 AI 重构学术合规新体验
  • 【电路】过压保护电路
  • OFA模型为Python开源项目自动生成README中的示例效果图描述
  • FFmpeg批量抽帧实战:为C3D模型准备UCF101图像序列的避坑指南
  • 从设计到验证:Bandgap基准电路的全流程仿真实践
  • Fun-ASR常见问题解决:识别慢、准确率低、麦克风没反应,一招搞定
  • 昆明宝藏美容培训机构大揭秘,美业梦想起航地 - 品牌测评鉴赏家
  • 【电路】共模和差模的含义
  • 永磁同步电机的双环及三环控制仿真模型及参考资料
  • FFT算法完全指南:从数学原理到智能电表的谐波分析应用
  • Halcon仿射变换实战:用affine_trans_image搞定图像旋转缩放与拼接(附避坑指南)
  • 如何查看Oracle版本信息_v$version视图与opatch lsinventory
  • 为什么你的LLM+Agent仍无法做归因诊断?:从do-calculus到结构因果模型(SCM)的6步工程化落地路径
  • 实测不踩雷|2026国内靠谱美甲培训机构推荐,新手/创业者直接抄作业 - 品牌测评鉴赏家
  • 郑州宝藏美容培训学校大盘点,小白必看! - 品牌测评鉴赏家
  • OBS多平台直播插件终极指南:三步实现多平台同步推流
  • 大模型技术入门必看:Modular RAG演进与实战技巧,小白也能轻松掌握并收藏学习!
  • 实战指南:基于RGB活体检测的人脸识别系统开发