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

C语言增删查改实战:高效管理顺序表

        创建一个顺序表,并从键盘接收数字输入,将输入的正整数按从小到大的顺序插入顺序表,并在输入负整数的时候将其绝对值数据删除。每次输入后,将顺序表的内容打印到屏幕上。

        解析: 此题考查顺序表的基本思路,先要设计好顺序表的逻辑表达,再通过对顺序表的插入和删除操作,体会顺序存储中对于插入和删除的不便性。

参考代码

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>// 顺序表结构体定义
typedef struct {int total_size;  // 顺序表总容量int last;        // 顺序表最末元素的下标int *data;       // 顺序表的存储空间
} sqlist;// 初始化一个空的顺序表
sqlist *init_list(int total_size) {// 检查容量是否合法if (total_size <= 0) {fprintf(stderr, "初始化失败:容量必须为正数\n");return NULL;}sqlist *sq = (sqlist *)malloc(sizeof(sqlist));if (sq != NULL) {sq->total_size = total_size;sq->last = -1;  // 用-1表征当前没有元素sq->data = (int *)malloc(sizeof(int) * total_size);// 内存分配失败处理if (sq->data == NULL) {fprintf(stderr, "内存分配失败\n");free(sq);return NULL;}} else {fprintf(stderr, "内存分配失败\n");}return sq;
}// 释放顺序表占用的内存
void destroy_list(sqlist *sq) {if (sq != NULL) {free(sq->data);  // 先释放数据区free(sq);        // 再释放结构体}
}// 判断顺序表是否为空
bool is_empty(sqlist *sq) {return (sq != NULL) && (sq->last == -1);
}// 判断顺序表是否已满
bool is_full(sqlist *sq) {return (sq != NULL) && (sq->last >= sq->total_size - 1);
}// 在递增的顺序表中找到x应插入的合适位置
int get_pos(sqlist *sq, int x) {if (sq == NULL || is_empty(sq)) {return 0;  // 空表时返回0}int pos = 0;while ((pos <= sq->last) && (sq->data[pos] < x)) {pos++;}return pos;
}// 在顺序表sq中,定位元素x(内部使用,不打印信息)
int find_pos(sqlist *sq, int x) {if (sq == NULL || is_empty(sq)) {return -1;}for (int pos = 0; pos <= sq->last; pos++) {if (sq->data[pos] == x) {return pos;}}return -1;
}// 在顺序表sq中,定位元素x(外部使用,打印信息)
int locate(sqlist *sq, int x) {int pos = find_pos(sq, x);if (pos != -1) {printf("找到元素: data[%d] = %d\n", pos, x);} else {printf("未找到元素: %d\n", x);}return pos;
}// 将元素x插入顺序表sq中
bool insert(sqlist *sq, int x) {// 参数检查if (sq == NULL) {fprintf(stderr, "插入失败:顺序表未初始化\n");return false;}// 检查是否已满if (is_full(sq)) {fprintf(stderr, "插入失败:顺序表已满\n");return false;}// 找到插入位置int pos = get_pos(sq, x);// 移动元素for (int i = sq->last; i >= pos; i--) {sq->data[i + 1] = sq->data[i];}// 插入元素sq->data[pos] = x;sq->last++;printf("已插入元素: %d\n", x);return true;
}// 从顺序表中将元素x剔除
bool delete(sqlist *sq, int x) {// 参数检查if (sq == NULL) {fprintf(stderr, "删除失败:顺序表未初始化\n");return false;}// 检查是否为空if (is_empty(sq)) {fprintf(stderr, "删除失败:顺序表为空\n");return false;}// 查找元素位置(直接调用内部函数,避免重复遍历)int pos = find_pos(sq, x);if (pos == -1) {fprintf(stderr, "删除失败:元素 %d 不存在\n", x);return false;}// 移动元素覆盖要删除的位置for (; pos < sq->last; pos++) {sq->data[pos] = sq->data[pos + 1];}sq->last--;printf("已删除元素: %d\n", x);return true;
}// 展示顺序表元素
void show_data(sqlist *sq) {if (sq == NULL) {fprintf(stderr, "顺序表未初始化\n");return;}if (is_empty(sq)) {printf("顺序表为空\n");printf("=======================\n");return;}printf("当前顺序表元素:\n");for (int i = 0; i <= sq->last; i++) {printf("\tdata[%d] = %d\n", i, sq->data[i]);}printf("=======================\n");
}int main(int argc, char *argv[]) {// 初始化一条空的顺序表,容量为10sqlist *sq = init_list(10);if (sq == NULL) {return 1;  // 初始化失败则退出}int num;printf("请输入操作(正数插入,负数删除,0退出):\n");while (1) {// 读取输入并验证printf("输入:");if (scanf("%d", &num) != 1) {fprintf(stderr, "输入错误,请输入整数\n");// 清除输入缓冲区while (getchar() != '\n');continue;}if (num > 0) {// 插入元素insert(sq, num);show_data(sq);} else if (num < 0) {// 删除元素(取绝对值)delete(sq, -num);show_data(sq);} else {// 退出程序printf("程序结束\n");break;}}// 释放内存destroy_list(sq);return 0;
}

优缺点总结

        顺序存储中,由于逻辑关系是用物理位置来表达的,因此从上述示例代码可以很清楚看到,增删数据都非常困难,需要成片地移动数据。顺序表对数据节点的增删操作是很不友好的。

总结其特点如下:

优点:

  1. 不需要多余的信息来记录数据间的关系,存储密度高
  2. 所有数据顺序存储在一片连续的内存中,支持立即访问任意一个随机数据,比如上述顺序表中第i个节点是 s->data[i]访问快

缺点:

  1. 插入、删除时需要保持数据的物理位置反映其逻辑关系,一般需要成片移动数据(增删慢
  2. 当数据节点数量较多时,需要一整片较大的连续内存空间(需要提前确定大小
  3. 当数据节点数量变化剧烈时,内存的释放和分配不灵活(需要整体释放
http://www.dtcms.com/a/326822.html

相关文章:

  • docker安装searxng
  • monorepo架构设计方案
  • CICD部署流程详解文档笔记
  • 在 Ubuntu 中docker容器化操作来使用新建的 glibc-2.32
  • [激光原理与应用-244]:设计 - 光学 - CLBO晶体使用一段时间后,输出功率就会下降,原因有哪些?
  • OpenBMC中的snk-psu-manager:架构、原理与应用深度解析
  • 高防IP能为网站防御哪些网络攻击?
  • 从零开始学JAVAWeb-5
  • 腾讯云Edgeone限时免费
  • for循环详解与实战技巧
  • Edit Distance
  • 传统制造业减人不减效:一线用工优化的3个投入方向,用对工具比盲目裁员更关键
  • 对抗样本攻击检测与防御
  • 车载软件架构 --- 车辆量产后怎么刷写Flash Bootloader
  • BLE ADV
  • special topic 9 (2) and 1011(1)division one
  • 深入解析Windows系统下UDP绑定失败的原理与系统级解决方案
  • 数据库三范式入门教程
  • Windows11 PowerShell CMD
  • Ascend DrivingSDK 中的 modulated_deform_conv2d(一)
  • GESP2023年9月认证C++一级( 第三部分编程题(1)买文具)
  • MATLAB实现遗传算法求解路网路由问题
  • PTE之路--03文
  • 【08-神经网络介绍】
  • 北京-4年功能测试2年空窗-报培训班学测开-第七十三天-投递简历-[特殊字符][特殊字符]
  • Linux驱动学习day27天(USB驱动理论部分)
  • SSR-code 项目复刻与3D模型生成实现
  • nomachine的安装和使用
  • 华清远见25072班C语言学习day6
  • 操作系统1.5:操作系统引导