news 2026/7/12 3:07:40

C语言数据结构课设:航空订票系统链表与队列实战(附完整源码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言数据结构课设:航空订票系统链表与队列实战(附完整源码)

C语言数据结构课设:航空订票系统链表与队列实战

航空订票系统是数据结构课程设计的经典案例,它完美融合了链表和队列这两种基础数据结构。本文将深入探讨如何用C语言实现一个功能完整的航空订票系统,重点分析数据结构的选择依据、核心算法设计思路以及实际编码中的关键技巧。

1. 系统架构设计

1.1 需求分析与数据结构选择

航空订票系统需要管理两类核心数据:航班信息和乘客信息。每条航班包含以下字段:

  • 起点站、终点站
  • 航班编号、飞机号
  • 飞行日期(星期几)
  • 总票数、余票量
  • 不同舱位的余票量(如经济舱、商务舱)

乘客信息则需要记录:

  • 姓名、身份证号
  • 订票数量、舱位等级
  • 飞行日期

链表是管理航班信息的理想选择,因为:

  • 航班数量动态变化(可能新增或取消航班)
  • 需要频繁的插入和删除操作
  • 内存利用率高,不需要预先分配固定空间

队列则用于处理候补订票需求,符合"先到先服务"的业务规则。当某航班票已售罄时,后续请求进入候补队列,有空余票时按顺序处理。

1.2 核心数据结构定义

// 乘客节点(用于已订票乘客链表) typedef struct CNode { char name[20]; // 姓名 int num; // 订票数 char ID[20]; // 身份证 char day[20]; // 飞行日期 int dengji; // 舱位等级 struct CNode *next; // 下一乘客指针 } CNode, *CList; // 候补队列节点 typedef struct HbNode { char name[20]; // 姓名 char ID[20]; // 身份证 int num; // 预定数量 struct HbNode *next;// 下一候补指针 } QhbNode, *Phb; // 候补队列结构 typedef struct Queue { Phb front; // 队头指针 Phb rear; // 队尾指针 } LinkQueue; // 航班节点(带头结点的单链表) typedef struct hangban { char qidian[20]; // 起点站 char zhongdian[20]; // 终点站 char hbID[20]; // 航班编号 char hbnum[20]; // 飞机号 char day[20]; // 飞行日期 int maxnum; // 总票数 int less; // 余票量 int lessgrade1; // 等级1余量 int lessgrade2; // 等级2余量 hangban *next; // 下一航班指针 CList cusLinkList; // 乘客链表头指针 LinkQueue wQgrade1; // 等级1候补队列 LinkQueue wQgrade2; // 等级2候补队列 } hangban, *Phangban;

2. 核心功能实现

2.1 航班链表管理

航班链表采用带头结点的单链表结构,方便统一处理插入和删除操作。初始化时需要创建头结点:

void initFlight() { pFlight = (hangban *)malloc(sizeof(hangban)); if (pFlight == NULL) exit(0); pFlight->next = NULL; // 初始为空链表 }

航班插入操作需要考虑航班编号的唯一性。通过遍历链表检查是否已存在相同编号:

int duibiFlight(hangban *flight, char ID[]) { hangban *p = flight; while (p != NULL) { if (!strcmp(ID, p->hbID)) return 0; // 编号重复 p = p->next; } return 1; // 编号可用 }

2.2 订票业务逻辑

订票是系统最复杂的功能,需要处理多种情况:

  1. 有余票时直接订票
  2. 余票不足时询问是否候补
  3. 候补队列管理
void dingpiao() { hangban *info = find(); // 查找航班 if (info == NULL) { printf("不存在该航班!\n"); return; } // 获取用户输入 printf("请输入您想要定的票数:"); int need; scanf("%d", &need); printf("请输入您的票的舱位等级(1或2):"); int grade; scanf("%d", &grade); // 检查余票 int num = (grade == 1) ? info->lessgrade1 : info->lessgrade2; if (need <= num) { // 有余票,处理订票 char name[20], id[20], day[20]; printf("请输入您的姓名:"); scanf("%s", name); printf("请输入您的身份证号码:"); scanf("%s", id); printf("请输入你的飞行周期:"); scanf("%s", day); // 添加到乘客链表 CList head = info->cusLinkList; addlink(head, need, name, id, day, grade); // 更新余票 info->less -= need; if (grade == 1) info->lessgrade1 -= need; else info->lessgrade2 -= need; printf("\n订票成功!\n"); } else { // 余票不足 printf("该等级的票不足!\n"); printf("是否排队等候?(Y/N)"); char r = getch(); if (r == 'Y' || r == 'y') { // 加入候补队列 char name[20], id[20]; printf("\n请输入您的姓名(排队订票):"); scanf("%s", name); printf("\n请输入您的身份证(排队订票):"); scanf("%s", id); if (grade == 1) info->wQgrade1 = enqueue(info->wQgrade1, name, need, id); else info->wQgrade2 = enqueue(info->wQgrade2, name, need, id); printf("\n排队成功!\n"); } } }

2.3 退票与候补处理

退票时需要检查乘客信息匹配,并触发候补队列处理:

void tuipiao() { hangban *info = find(); // 查找航班 if (info == NULL) return; // 获取用户信息 char name[20], id[20], day[20]; printf("请输入你的姓名: "); scanf("%s", name); printf("请输入你的身份证号码: "); scanf("%s", id); printf("请输入飞行周期: "); scanf("%s", day); // 在乘客链表中查找 CNode *p1 = info->cusLinkList->next; CNode *p2 = info->cusLinkList; while (p1 != NULL) { if (strcmp(name, p1->name)==0 && strcmp(id, p1->ID)==0 && strcmp(day, p1->day)==0) break; p2 = p1; p1 = p1->next; } if (p1 == NULL) { printf("退票信息不匹配!\n"); return; } // 执行退票 int grade = p1->dengji; int num = p1->num; p2->next = p1->next; free(p1); // 恢复余票 info->less += num; if (grade == 1) info->lessgrade1 += num; else info->lessgrade2 += num; printf("%s 成功退票!\n", name); // 处理候补队列 processWaitQueue(info, grade); }

候补队列处理函数会检查队列头部乘客是否能满足订票需求:

void processWaitQueue(hangban *info, int grade) { LinkQueue *queue = (grade == 1) ? &(info->wQgrade1) : &(info->wQgrade2); int *less = (grade == 1) ? &(info->lessgrade1) : &(info->lessgrade2); while (!isQueueEmpty(queue) && queue->front->next->num <= *less) { Phb node = dequeue(queue); printf("通知候补乘客 %s:已有余票,请办理订票手续\n", node->name); *less -= node->num; info->less -= node->num; free(node); } }

3. 关键算法优化

3.1 航班查找优化

原始实现中,每次查找航班都需要遍历整个链表,时间复杂度为O(n)。可以通过以下方式优化:

  1. 哈希表索引:建立航班编号到节点指针的哈希映射
  2. 排序链表:保持链表按编号有序,使用二分查找
  3. 跳表结构:构建多级索引加速查找
// 哈希表优化示例 #define HASH_SIZE 100 hangban* hashTable[HASH_SIZE]; int hashFunc(char *id) { int sum = 0; for (int i = 0; id[i]; i++) sum += id[i]; return sum % HASH_SIZE; } void insertHash(hangban *node) { int index = hashFunc(node->hbID); node->nextHash = hashTable[index]; hashTable[index] = node; } hangban* findHash(char *id) { int index = hashFunc(id); hangban *p = hashTable[index]; while (p != NULL) { if (strcmp(p->hbID, id) == 0) return p; p = p->nextHash; } return NULL; }

3.2 内存管理改进

原始代码中频繁使用malloc/free,可能导致内存碎片。可以考虑:

  1. 内存池技术:预先分配大块内存,自行管理分配释放
  2. 对象池:对常用结构体(如乘客节点)建立回收机制
#define POOL_SIZE 1000 CNode nodePool[POOL_SIZE]; int nodeIndex = 0; CNode* allocNode() { if (nodeIndex >= POOL_SIZE) return NULL; return &nodePool[nodeIndex++]; } void freeNode(CNode *node) { // 标记为可复用即可 }

4. 系统测试与验证

4.1 测试用例设计

完整测试应覆盖以下场景:

测试类型测试用例预期结果
正常订票有余票时订票订票成功,余票减少
边界测试订票数等于余票订票成功,余票为0
异常测试订票数超过余票提示余票不足,询问是否候补
退票测试有效退票退票成功,余票增加
候补测试退票后触发候补通知队列首位的候补乘客

4.2 内存泄漏检查

使用valgrind等工具检查内存泄漏:

valgrind --leak-check=full ./airline_system

常见内存问题包括:

  • 节点删除后未free
  • 异常路径下资源未释放
  • 指针操作错误导致的内存越界

5. 项目扩展方向

5.1 持久化存储

当前系统数据仅保存在内存中,可以扩展文件存储功能:

void saveToFile(Phangban flight, const char* filename) { FILE *fp = fopen(filename, "wb"); if (fp == NULL) return; hangban *p = flight->next; while (p != NULL) { fwrite(p, sizeof(hangban), 1, fp); // 需要单独保存乘客链表和候补队列 p = p->next; } fclose(fp); } void loadFromFile(Phangban flight, const char* filename) { FILE *fp = fopen(filename, "rb"); if (fp == NULL) return; hangban temp; while (fread(&temp, sizeof(hangban), 1, fp)) { hangban *q = (hangban *)malloc(sizeof(hangban)); *q = temp; q->next = flight->next; flight->next = q; } fclose(fp); }

5.2 多线程支持

引入线程安全机制支持并发访问:

pthread_mutex_t flight_mutex = PTHREAD_MUTEX_INITIALIZER; void safeDingpiao() { pthread_mutex_lock(&flight_mutex); dingpiao(); pthread_mutex_unlock(&flight_mutex); } void safeTuipiao() { pthread_mutex_lock(&flight_mutex); tuipiao(); pthread_mutex_unlock(&flight_mutex); }

5.3 图形界面

使用GTK或Qt添加图形界面:

// GTK简单示例 void create_main_window() { GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "航空订票系统"); GtkWidget *button = gtk_button_new_with_label("查询航班"); g_signal_connect(button, "clicked", G_CALLBACK(query_flights), NULL); gtk_container_add(GTK_CONTAINER(window), button); gtk_widget_show_all(window); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 3:07:38

CTFShow 萌新区 47 题 WP 精讲:Web 1-10 篇,5 种 intval 绕过实战

CTFShow 萌新区 Web 1-10 题精讲&#xff1a;5 种 intval 绕过手法实战剖析在 CTF 竞赛的 Web 安全领域中&#xff0c;PHP 类型转换漏洞一直是高频考点。本文将系统性地剖析 CTFShow 萌新区 Web 1-10 题中 intval() 函数的 5 种经典绕过手法&#xff0c;通过原理分析、Payload …

作者头像 李华
网站建设 2026/7/12 3:07:33

UG NX 2406 + VS2022 C++ 二次开发:从零配置到生成首个DLL的5个关键步骤

UG NX 2406 VS2022 C 二次开发&#xff1a;从零配置到生成首个DLL的5个关键步骤在工业设计领域&#xff0c;UG NX作为一款功能强大的CAD/CAM/CAE集成软件&#xff0c;其二次开发能力为工程师提供了极大的定制化空间。本文将详细介绍如何基于最新版本的UG NX 2406和Visual Stud…

作者头像 李华
网站建设 2026/7/12 3:07:28

基于TC78H651AFNG和PIC18F85K22的直流电机驱动方案

1. 项目背景与核心器件选型在工业自动化和消费电子领域&#xff0c;直流有刷电机因其结构简单、控制方便、成本低廉等优势&#xff0c;仍然是运动控制系统的首选执行元件。而驱动器的性能直接决定了整个运动控制系统的响应速度、能效比和可靠性。TC78H651AFNG作为东芝新一代DMO…

作者头像 李华
网站建设 2026/7/12 3:06:08

便携式文件夹加密器V5.43:AES-256算法与数据安全实践指南

1. 项目概述&#xff1a;为什么我们需要一个“便携式”加密器&#xff1f;在数字生活里&#xff0c;我们的电脑硬盘就像是一个巨大的、没有上锁的抽屉。工作文档、私人照片、财务记录、项目源码……所有这些敏感信息都混杂在一起。你可能觉得“我的电脑有开机密码”&#xff0c…

作者头像 李华
网站建设 2026/7/12 3:05:55

3个关键步骤让老Mac焕发新生:OpenCore Legacy Patcher终极指南

3个关键步骤让老Mac焕发新生&#xff1a;OpenCore Legacy Patcher终极指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否曾经看着手中的老款Mac电脑&…

作者头像 李华
网站建设 2026/7/12 3:05:53

影刀RPA 农产品价格监控:批发市场行情自动采集

影刀RPA 农产品价格监控&#xff1a;批发市场行情自动采集 作者&#xff1a;林焱 | 分类&#xff1a;影刀RPA新手教程 | 难度&#xff1a;★★ 什么情况用 做农产品贸易、社区团购、食堂采购的朋友&#xff0c;每天都要盯批发市场价格。北京新发地、广州江南、上海江桥……每家…

作者头像 李华