一、問題陳述
宿舍對於大學生在校生活來說相當於家的存在,而宿舍管理又是學校後勤管理的重要環節,如何直觀的瞭解宿舍的入住情況和每位同學的住宿位置是提高工作效率的重要課題,根據我們所學的C語言和數據結構課程中有關鏈表的內容,爲宿舍管理人員編寫宿舍管理查詢軟件,就可以輕鬆滿足實現上述需求。
任務:
- 爲宿舍管理人員編寫一個宿舍管理查詢軟件, 程序設計要求:
- 採用交互工作方式
- 可按關鍵字(姓名、學號、房號)進行排序
- 查詢菜單: (用二分查找實現以下操作)
- 按姓名查詢
- 按學號查詢
- 按房號查詢
- 打印任一查詢結果(可以連續操作)
二、概要設計
2.1 概要簡述
根據系統要求,即本系統具有信息的錄入,顯示,排序顯示、查找,插入、刪除、結束程序等功能,先設計出詳細的系統流程圖,然後將源代碼輸入程序,進行編譯調試即可。
程序總體分10個項目:輸入記錄、顯示記錄、按姓名排序並顯示、按房間號排序並顯示 、按學號排序並顯示 、按姓名查找並顯示 、按房間號查找並顯示 、按學號查找並顯示、插入一條記錄按學號排序並顯示以及結束程序。
2.2 線性表存儲結構表示
typedef struct {
char name[20];
int num; //學號和房號都爲整型
int room;
} stu;
typedef struct {
int length; //當前長度
stu *elem; //存儲空間基址
int listsize; //當前分配的存儲容量
} linklist;
2.3 詳細設計
2.3.1 系統流程圖
2.3.2 三種排序方法及二分查找法
2.3.2.1 冒泡排序(按姓名排序)
//按姓名排序(採用冒泡排序)
void sort1(linklist &L) {
int i, j;
stu temp;
for (i = 0; i<L.length - 1; i++)
for (j = 0; j<L.length-1-i; j++)
if (strcmp(L.elem[j].name, L.elem[j+1].name)>0) {
temp = L.elem[j];
L.elem[j] = L.elem[j+1];
L.elem[j+1] = temp;
}
}
2.3.2.2 折半插入排序(按學號排序)
//按學號排序(採用折半插入排序)
void sort2(linklist &L) {
int i, j, mid, low, high;
stu temp;
for (i = 1; i < L.length; i++) {
if(L.elem[i].num<L.elem[i-1].num) {
temp = L.elem[i];
low = 0;
high = i-1;
while (low <= high) {
mid = (low + high) / 2;
if (temp.num < L.elem[mid].num)
high = mid - 1;
else
low = mid + 1;
}
for (j = i - 1; j >= high+1; j--)
L.elem[j+1]=L.elem[j];
L.elem[high+1]=temp;
}
}
}
2.3.2.3 簡單選擇排序(按房號排序)
//按房號排序(採用簡單選擇排序)
void sort3(linklist &L) {
int i,j,k;
stu temp;
for(i=0; i<L.length-1; i++) {
k=i;
for(j=i+1; j<L.length; j++)
if(L.elem[j].room<L.elem[k].room)
k=j;
if(k!=i){
temp = L.elem[i];
L.elem[i] = L.elem[k];
L.elem[k] = temp;
}
}
}
2.3.2.4 二分查找法(以按姓名查找爲例)
//按姓名從小到大查找(採用二分查找)
void search1(linklist &L) {
if (L.length == 0) {
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
int low = 0, high = L.length, mid, flag = 0;
printf("\n");
printf("按姓名查找-->請輸入要查找的姓名:");
char a[15], ch;
scanf("%s", a);
while (low <= high) {
mid = (low + high) / 2;
if (strcmp(a, L.elem[mid].name) == 0) {
flag = 1;
break;
} else if (strcmp(a, L.elem[mid].name)>0)
low = mid + 1;
else
high = mid - 1;
}
if (flag == 1) {
printf("查找成功-->該學生信息爲:\n");
printf("姓名 學號 房號\n");
printf("%-10s %-2d %-5d\n", L.elem[mid].name, L.elem[mid].num, L.elem[mid].room);
if (Select())
search1(L);
else {
system("cls");
Menu();
}
} else {
printf("該學生不存在!");
if (Select()) search1(L);
else {
system("cls");
Menu();
}
}
}
}
三、測試與運行
3.1 系統界面
3.2 新建宿舍名單
3.3 排序(以姓名排序爲例)
3.4 查詢(以學號查詢爲例)
3.5 插入學生信息
3.6 刪除學生信息
四、代碼實現
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#define N 40 //線性表存儲空間的初始分配量
#define increase 10 //線性表存儲空間的分配量增量
int choice; //定義全局變量
typedef struct {
char name[20];
int num; //學號和房號都爲整型
int room;
} stu;
stu stud;
typedef struct {
int length; //當前長度
stu *elem; //存儲空間基址
int listsize; //當前分配的存儲容量
} linklist;
//線性表初始化
void Init(linklist &L) {
L.length = 0;
L.elem = (stu *)malloc(N * sizeof(stu));
L.listsize = N;
}
//操作菜單
void Menu() {
printf( "**************************************\n" );
printf( "*** 歡迎進入宿舍管理系統 ***\n" );
printf( "**************************************\n" );
printf( "* 1. 新建宿舍名單 *\n" );
printf( "* 2. 排序宿舍信息 *\n" );
printf( "* 3. 查詢宿舍信息 *\n" );
printf( "* 4. 插入宿舍信息 *\n" );
printf( "* 5. 刪除宿舍信息 *\n" );
printf( "* 0. 退出系統 *\n" );
printf( "**************************************\n" );
printf("請輸入菜單(0-5):");
scanf("%d", &choice);
if (choice<0 || choice>5) {
system("cls");
printf("輸入數字不對,請重新!\n");
printf("\n");
Menu();
}
}
//打印學生信息
void Display(linklist &L) {
int i;
printf("姓名 學號 房號\n");
for (i = 0; i<L.length; i++)
printf("%-10s %-2d %5d\n", L.elem[i].name, L.elem[i].num, L.elem[i].room);
}
//返回主界面
void Ret() {
char c;
fflush(stdin);
printf("\n");
printf("請按任意鍵進入主界面:");
scanf("%c", &c);
system("cls");
}
//創建學生信息表
void Create(linklist &L) {
if (L.length >= L.listsize) { //判斷學生的人數是否超過初值,如果超過,則重新分配
stu *newbase;
newbase = (stu*)realloc(L.elem, (N + increase) * sizeof(stu));
L.elem = newbase;
L.listsize += increase;
}
int i = 2;
char ch;
printf("********開始創建學生信息**********\n");
printf("\n");
printf("請輸入第1個學生的信息\n");
printf("請輸入姓名:");
fflush(stdin); // 清空輸入緩衝區,得到正確的輸入數據
gets(stud.name); //輸入一行字符串(姓名)
printf("請輸入學號:");
scanf("%d", &stud.num);
printf("請輸入房號:");
scanf("%d", &stud.room);
ch = getchar();
strcpy(L.elem[L.length].name, stud.name);
L.elem[L.length].num = stud.num;
L.elem[L.length].room = stud.room;
L.length++;
printf("\n");
printf("是否繼續輸入?<y/n>:");
scanf("%c", &ch);
printf("\n");
while (ch == 'y') {
printf("請輸入第%d個學生的信息\n", i);
printf("請輸入姓名:");
fflush(stdin); // 清空輸入緩衝區,得到正確的輸入數據
gets(stud.name); //輸入一行字符串(姓名)
printf("請輸入學號:");
scanf("%d", &stud.num);
printf("請輸入房號:");
scanf("%d", &stud.room);
strcpy(L.elem[L.length].name, stud.name);
L.elem[L.length].num = stud.num;
L.elem[L.length].room = stud.room;
i++;
L.length=i-1;
ch = getchar();
printf("\n");
printf("是否繼續輸入?<y/n>:");
scanf("%c", &ch);
printf("\n");
}
if (ch == 'n')
system("cls");
}
//按姓名排序(採用冒泡排序)
void sort1(linklist &L) {
int i, j;
stu temp;
for (i = 0; i<L.length - 1; i++)
for (j = 0; j<L.length-1-i; j++)
if (strcmp(L.elem[j].name, L.elem[j+1].name)>0) {
temp = L.elem[j];
L.elem[j] = L.elem[j+1];
L.elem[j+1] = temp;
}
}
//按學號排序(採用折半插入排序)
void sort2(linklist &L) {
int i, j, mid, low, high;
stu temp;
for (i = 1; i < L.length; i++) {
if(L.elem[i].num<L.elem[i-1].num) {
temp = L.elem[i];
low = 0;
high = i-1;
while (low <= high) {
mid = (low + high) / 2;
if (temp.num < L.elem[mid].num)
high = mid - 1;
else
low = mid + 1;
}
for (j = i - 1; j >= high+1; j--)
L.elem[j+1]=L.elem[j];
L.elem[high+1]=temp;
}
}
}
//按房號排序(採用簡單選擇排序)
void sort3(linklist &L) {
int i,j,k;
stu temp;
for(i=0; i<L.length-1; i++) {
k=i;
for(j=i+1; j<L.length; j++)
if(L.elem[j].room<L.elem[k].room)
k=j;
if(k!=i){
temp = L.elem[i];
L.elem[i] = L.elem[k];
L.elem[k] = temp;
}
}
}
//排序函數
void Sort(linklist &L) {
int c;
printf("請輸入排序的方式(1:按名字排序,2:按學號排序,3:按房號排序):");
scanf("%d", &c);
switch (c) {
case 1:
sort1(L);
if (L.length == 0) {
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
printf("按姓名排序:\n");
Display(L);
Ret(); //調用返回主界面
Menu();
}
break;
case 2:
sort2(L);
if (L.length == 0) {
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
printf("按學號排序:\n");
Display(L);
Ret(); //調用返回主界面
Menu();
}
break;
case 3:
sort3(L);
if (L.length == 0) {
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
printf("按房號排序:\n");
Display(L);
Ret(); //調用返回主界面
Menu();
}
break;
default:
break;
}
}
//選擇是否繼續查找
int Select() {
char ch;
scanf("%c", &ch);
printf("是否繼續查找?<y/n>:");
fflush(stdin);
scanf("%c", &ch);
if (ch == 'y') {
system("cls");
return 1;
} else
return 0;
}
//按姓名從小到大查找(採用二分查找)
void search1(linklist &L) {
if (L.length == 0) {
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
int low = 0, high = L.length, mid, flag = 0;
printf("\n");
printf("按姓名查找-->請輸入要查找的姓名:");
char a[15], ch;
scanf("%s", a);
while (low <= high) {
mid = (low + high) / 2;
if (strcmp(a, L.elem[mid].name) == 0) {
flag = 1;
break;
} else if (strcmp(a, L.elem[mid].name)>0)
low = mid + 1;
else
high = mid - 1;
}
if (flag == 1) {
printf("查找成功-->該學生信息爲:\n");
printf("姓名 學號 房號\n");
printf("%-10s %-2d %-5d\n", L.elem[mid].name, L.elem[mid].num, L.elem[mid].room);
if (Select())
search1(L);
else {
system("cls");
Menu();
}
} else {
printf("該學生不存在!");
if (Select()) search1(L);
else {
system("cls");
Menu();
}
}
}
}
//按學號從小到大查找(採用二分查找)
void search2(linklist &L) {
if (L.length == 0) {
printf("\n");
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
int low = 0, high = L.length, mid, flag = 0;
int n;
char ch;
printf("\n");
printf("按學號查找-->請輸入要查找的學號:");
scanf("%d", &n);
while (low <= high) {
mid = (low + high) / 2;
if (n == L.elem[mid].num) {
flag = 1;
break;
} else if (n>L.elem[mid].num)
low = mid + 1;
else
high = mid - 1;
}
if (flag == 1) {
printf("查找成功----->該學生信息爲:\n");
printf("姓名 學號 房號\n");
printf("%-1s0 %-2d %-5d\n", L.elem[mid].name, L.elem[mid].num, L.elem[mid].room);
if (Select())
search2(L);
else {
system("cls");
Menu();
}
} else {
printf("該學生不存在!");
if (Select())
search2(L);
else {
system("cls");
Menu();
}
}
}
}
//按房號從小到大查找(採用二分查找)
void search3(linklist &L) {
if (L.length == 0) { //此函數功能爲:返回主界面
printf("\n");
printf("已無學生記錄!\n");
Ret();
Menu();
} else {
int low = 0, high = L.length, mid, flag = 0;//flag作爲標誌符,爲1則表示查找成功,否則沒有所要查找的學生
int m;
char ch;
printf("\n");
printf("按房號查找-->請輸入要查找的房號:");
scanf("%d", &m);
while (low <= high) {
mid = (low + high) / 2;
if (m == L.elem[mid].room) {
flag = 1;
break;
} else if (m>L.elem[mid].room)
low = mid + 1;
else
high = mid - 1;
}
if (flag == 1) {
printf("查找成功-->該學生信息爲:\n");
printf("姓名 學號 房號\n");
printf("%-10s %-2d %-5d\n", L.elem[mid].name, L.elem[mid].num, L.elem[mid].room);
if (Select()) //調用判斷函數1
search3(L);
else {
system("cls");
Menu();
}
} else {
printf("該學生不存在!");
if (Select()) //調用判斷函數2
search3(L);
else {
system("cls");
Menu();
}
}
}
}
//查找函數
void Search(linklist &L) {
int c;
printf("請輸入查找的方式(1:按名字查找,2:按學號查找,3:按房號查找):");
scanf("%d", &c);
switch (c) {
case 1:
sort1(L);
search1(L);
break;//先進行二分查找排序
case 2:
sort2(L);
search2(L);
break;
case 3:
sort3(L);
search3(L);
break;
default:
break;
}
}
//按學號從小到大插入該學生
void Insert(linklist &L) {
int i, j, k;
char ch;
printf("\n");
printf("插入的學生信息爲:\n");
printf("姓名:");
fflush(stdin);// 清空輸入緩衝區,得到正確的輸入數據
gets(stud.name);
printf("學號:");
scanf("%d", &stud.num);
printf("房號:");
scanf("%d", &stud.room);
if (L.length == 0) {
strcpy(L.elem[L.length].name, stud.name);
L.elem[L.length].num = stud.num;
L.elem[L.length].room = stud.room;
}
for (i = 0; i<L.length; i++) {
if (stud.num<L.elem[i].num) {
k = i;
for (j = L.length; j>k; j--)
L.elem[j] = L.elem[j - 1];
strcpy(L.elem[k].name, stud.name);
L.elem[k].num = stud.num;
L.elem[k].room = stud.room;
break;
} else {
strcpy(L.elem[L.length].name, stud.name);
L.elem[L.length].num = stud.num;
L.elem[L.length].room = stud.room;
}
}
L.length++;
fflush(stdin);
printf("\n");
printf("是否繼續插入?<y/n>:");
scanf("%c", &ch);
if (ch == 'y') Insert(L);
else system("cls");
}
//按學號刪除該學生
void Delete(linklist &L) {
int i, j, k = -1;
char ch;
printf("\n");
printf("\n");
printf("請輸入要刪除學生的學號:");
scanf("%d", &stud.num);
for (i = 0; i<L.length; i++) {
if (stud.num == L.elem[i].num) {
printf("該學生的信息爲:\n");
printf("姓名:%s \n學號:%d \n房號:%d\n", L.elem[i].name, L.elem[i].num, L.elem[i].room);
k = i;
for (j = k; j<L.length - 1; j++)
L.elem[j] = L.elem[j + 1];
printf("已成功刪除\n");
break;
}
}
if (i >= L.length) printf("該學生不存在\n");
if (k >= 0)L.length--;
fflush(stdin);
printf("\n");
printf("是否繼續刪除操作?<y/n>:");
scanf("%c", &ch);
system("cls");
if (ch == 'y') Delete(L);
else system("cls");
}
//主函數
int main() {
linklist L; //定義線性表 L
Init(L);
Menu(); //調用主菜單函數
while (choice != 0) {
system("cls");
switch (choice) {
case 1:
Create(L); //調用線性表創建函數
Menu();
break;
case 2:
Sort(L);
break;//調用排序函數
case 3:
Search(L);
break;//調用查找函數進行(二分)查找
case 4:
sort2(L); //調用學號排序函數
Insert(L); //按學號序列插入
system("cls");
printf("插入後的學生信息:\n");
Display(L);
Ret();
Menu();
break;
case 5:
Delete(L); //調用刪除函數
if (L.length == 0) {
printf("\n");
printf("學生記錄已被刪除完!\n");
Ret();
Menu();
} else {
printf("顯示刪除後的學生信息:\n");
Display(L);
Ret();
Menu();
}
break;
}
}
}