图书信息管理系统

#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;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章