圖書信息管理系統

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<string>
using namespace std;
typedef struct BOOK{
	string ISBN;
	string name;
	int rate;
}BOOK;
typedef struct BOOK* ElemType;
typedef struct BookSystem* LinkBook;
typedef struct BookSystem{
	ElemType data;
	LinkBook next;
}BookSystem;
//初始化
void InitBook(LinkBook &B){
	B = new BookSystem;
	B->data = new BOOK;
	B->next = NULL;
	return;
}
//查找(名字)
LinkBook LocateBook(LinkBook B, string name){
	while (B){
		if (B->data->name == name)return B;
		B = B->next;
	}
	return NULL;
}
//插入(遞歸)
void InsertBook(LinkBook &B, BOOK e){
	if (!B){
		InitBook(B);
		*B->data = e;
	}
	else{
		InsertBook(B->next, e);
	}
	return;
}
//刪除(名字)(遞歸)
void DeleteBook(LinkBook &B, string name,LinkBook f){
	//f是B父親用來掛接
	if (!B)return;//未找到邊界
	if (B->data->name == name){
		LinkBook q = B;
		B = B->next;
		if (f)
		f->next = B;
		delete q;
		return;
	}
	else{
		f = B;
		DeleteBook(B->next, name,f);
	}
	return;
}
//修改(名字)
void ChangeBook(LinkBook &B, string OLD,string NEW){
	LinkBook change = (LocateBook(B, OLD));
	if (change)
		change->data->name = NEW;
	else
		cout << "沒有該書目"<<endl;
	return;
}
//找鏈尾
LinkBook LocateRear(LinkBook B){
	while (B->next)
		B = B->next;
	return B;
}
void swap(BOOK &a, BOOK &b){
	BOOK t = a;
	a = b;
	b = t;
	return;
}
//找樞軸
LinkBook GetPrivot(LinkBook start,LinkBook end){
	LinkBook p=start, q=p->next;
	BOOK t, key = *start->data;
	while (q!=end){
		while (q->data->ISBN.compare(key.ISBN) ==1&& q != end)
			q = q->next;
		if (q->data->ISBN.compare(key.ISBN)==-1){
			p = p->next;
			swap(*p->data,* q->data);
		}
	}
	swap(*start->data, *p->data);
	return p;
}
//排序
void QuickSortBook(LinkBook start,LinkBook end){
	if (start != end){
		LinkBook privot = GetPrivot(start, end);
		if (privot)
			QuickSortBook(start, privot);
		if (privot->next)
			QuickSortBook(privot->next, end);
	}
}
//計數
int LengthBook(LinkBook B){
	int len = 0;
	for (; B; len++)
		B = B->next;
	return len;
}
//輸出
void OutPut(LinkBook B){
	if (!B){ cout << "空" << endl; return; }
	while (B){
		cout << B->data->ISBN << " " << B->data->name << " " << B->data->rate << endl;
		B = B->next;
	}
	return;
}
//菜單
void menu(LinkBook B){
	printf("1.Locate;2.Insert;3.Delete;4.Change;5.QuickSort;6.Length;7.OutPut;8.end\n");
	char op;
	ElemType temp=new BOOK,result=new BOOK;
	while (1){
		fflush(stdin);
		op = getchar();
		fflush(stdin);
		switch (op)
		{
		case '1':
			printf("查找(名字):");
			cin >> temp->name;
			if (LocateBook(B, temp->name)){
				*result = *LocateBook(B, temp->name)->data;
				cout << result->ISBN << " " << result->name << " " << result->rate << endl;
			}
				else
				cout << "未找到\n";
			break;
		case '2':
			printf("插入(IBSN/name/rate):");
			cin >> temp->ISBN >> temp->name >> temp->rate;
			InsertBook(B, *temp);
			break;
		case '3':
			printf("刪除(name):");
			cin >> temp->name;
			DeleteBook(B, temp->name,NULL);
			break;
		case '4':
			printf("修改(名字 OLD/NEW):");
			cin >> temp->name>>result->name;
			ChangeBook(B, temp->name, result->name);
			break;
		case '5':
			printf("排序:\n");
			QuickSortBook(B, LocateRear(B));
			OutPut(B);
			break;
		case '6':
			printf("表長:%d\n", LengthBook(B));
			break;
		case '7':
			OutPut(B);
			break;
		case '8':
			return;
		default:
			cout << "WRONG\n";
			break;
		}
	}
}

int main(){
	LinkBook book=NULL;
	menu(book);
	system("PAUSE");
	return 0;
}

0.結構體

typedef struct BOOK{
	string ISBN;
	string name;
	int rate;
}BOOK;
typedef struct BOOK* ElemType;
typedef struct BookSystem* LinkBook;
typedef struct BookSystem{
	ElemType data;
	LinkBook next;
}BookSystem;

1.初始化

//初始化
void InitBook(LinkBook &B){
	B = new BookSystem;
	B->data = new BOOK;
	B->next = NULL;
	return;
}

2.查找(按名字)

//查找(名字)
LinkBook LocateBook(LinkBook B, string name){
	while (B){
		if (B->data->name == name)return B;
		B = B->next;
	}
	return NULL;
}

3.插入(遞歸)

注意

1.可以利用初始化函數
利用該節點空時就初始化然後填數來遞歸實現插入
2.用遞歸和引用傳遞的好處是
用next遞歸:InsertBook(B->next, e);
遞歸完函數後B也發生了變化且B的根不變

//插入(遞歸)
void InsertBook(LinkBook &B, BOOK e){
	if (!B){
		InitBook(B);
		*B->data = e;
	}
	else{
		InsertBook(B->next, e);
	}
	return;
}

4.刪除(名字)(遞歸)(刪除的是鏈表中先出現符合條件的的那個名字)

注意

1.被刪除節點的父親->next需要重新掛接到被刪除節點的後導;若爲根節點則無父親,不需掛接
2.在改接了之後,要把被刪除的節點的存儲空間釋放
3.找完未找到時需要一個邊界if (!B)return;
4.用遞歸和引用傳遞的好處是
用next遞歸:DeleteBook(B->next, name,f);
遞歸完函數後B也發生了變化且B的根不變(若是根被刪根就是變成next)
5.不能利用查找,因爲直接查找並不知道其父親是誰,無法掛接

void DeleteBook(LinkBook &B, string name,LinkBook f){
	//f是B父親用來掛接
	if (!B)return;//未找到邊界
	if (B->data->name == name){
		LinkBook q = B;
		B = B->next;
		if (f)
		f->next = B;
		delete q;
		return;
	}
	else{
		f = B;
		DeleteBook(B->next, name,f);
	}
	return;
}

5.修改(名字)(修改的是鏈表中先出現符合條件的的那個名字)

注意

可以利用查找函數:若NULL則是沒有該數目,否則就直接修改

//修改(名字)
void ChangeBook(LinkBook &B, string OLD,string NEW){
	LinkBook change = (LocateBook(B, OLD));
	if (change)
		change->data->name = NEW;
	else
		cout << "沒有該書目"<<endl;
	return;
}

6.排序(快排)

學習於

https://blog.csdn.net/otuhacker/article/details/10366563

6.1注意

1.string字符串的比較若><=不能用時就用A.compare(B):大於就是1;等於就是0;小於就是-1

6.2原理

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

6.3鏈表可以做單邊的快排

1即q=start,p=q->next;其中p,q之間的數大於關鍵字,p之前的數小於關鍵字,最後把start的值和p交換讓p作爲樞軸
2按照樞軸分成左右表遞歸執行快排直到左右表空結束

6.4其中子函數的作用

1.找鏈尾:爲了一開始的start和end
2.找樞軸:就是一次快排,再通過樞軸分成左右表遞歸執行快排
3.swap:交換兩個的值

//找鏈尾
LinkBook LocateRear(LinkBook B){
	while (B->next)
		B = B->next;
	return B;
}
void swap(BOOK &a, BOOK &b){
	BOOK t = a;
	a = b;
	b = t;
	return;
}
//找樞軸
LinkBook GetPrivot(LinkBook start,LinkBook end){
	LinkBook p=start, q=p->next;
	BOOK t, key = *start->data;
	while (q!=end){
		while (q->data->ISBN.compare(key.ISBN) ==1&& q != end)
			q = q->next;
		if (q->data->ISBN.compare(key.ISBN)==-1){
			p = p->next;
			swap(*p->data,* q->data);
		}
	}
	swap(*start->data, *p->data);
	return p;
}
//排序
void QuickSortBook(LinkBook start,LinkBook end){
	if (start != end){
		LinkBook privot = GetPrivot(start, end);
		if (privot)
		QuickSortBook(start, privot);
		if (privot->next)
		QuickSortBook(privot->next, end);
	}
}

7.計數

//計數
int LengthBook(LinkBook B){
	int len = 0;
	for (; B; len++)
		B = B->next;
	return len;
}

8.輸出

//輸出
void OutPut(LinkBook B){
	if (!B){ cout << "空" << endl; return; }
	while (B){
		cout << B->data->ISBN << " " << B->data->name << " " << B->data->rate << endl;
		B = B->next;
	}
	return;
}

9.菜單

注意

1.fflush(stdin);是清空鍵盤緩存區stdin的

fflush(stdin);
		op = getchar();
		fflush(stdin);

這樣之前多餘的鍵盤緩存區的內容不會被getchar()吸收,之後的多餘輸出也不會影響操作中輸入的數據,確保了op吸收了輸出的一串字符中的第一個,其他的都被清空了(包括\n)
2.賦值注意一定要加星號鍵,以免把地址賦出去,因爲temp,result是所有操作暫存數的地方,但是地址都不變

//菜單
void menu(LinkBook B){
	printf("1.Locate;2.Insert;3.Delete;4.Change;5.QuickSort;6.Length;7.OutPut;8.end\n");
	char op;
	ElemType temp=new BOOK,result=new BOOK;
	while (1){
		fflush(stdin);
		op = getchar();
		fflush(stdin);
		switch (op)
		{
		case '1':
			printf("查找(名字):");
			cin >> temp->name;
			if (LocateBook(B, temp->name)){
				*result = *LocateBook(B, temp->name)->data;
				cout << result->ISBN << " " << result->name << " " << result->rate << endl;
			}
				else
				cout << "未找到\n";
			break;
		case '2':
			printf("插入(IBSN/name/rate):");
			cin >> temp->ISBN >> temp->name >> temp->rate;
			InsertBook(B, *temp);
			break;
		case '3':
			printf("刪除(name):");
			cin >> temp->name;
			DeleteBook(B, temp->name,NULL);
			break;
		case '4':
			printf("修改(名字 OLD/NEW):");
			cin >> temp->name>>result->name;
			ChangeBook(B, temp->name, result->name);
			break;
		case '5':
			printf("排序:\n");
			QuickSortBook(B, LocateRear(B));
			OutPut(B);
			break;
		case '6':
			printf("表長:%d\n", LengthBook(B));
			break;
		case '7':
			OutPut(B);
			break;
		case '8':
			return;
		default:
			cout << "WRONG\n";
			break;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章