图书管理系统——链表实现

实验要求:
定义一个包含图书信息(书号、书名、价格)的顺序表或者链表。要求实现下面功能:

  1. 读入相应的图书数据来完成图书信息表的创建。然后,输出图书表中的图书个数,同时逐行输出每本图书的信息。
  2. 由于某种原因物价上涨,书店计划提高图书价格,要求计算所有图书的平均价格,低于平均价格的图书价格涨价10%,高于或等于平均价格的图书价格涨价5%,并输出调价后的图书信息。
  3. 将读入图书的信息逆序存储,逐行输出逆序存储后的每本图书的信息。反转链表
  4. 找出最贵的图书,并输出其信息。若有多本,则先输出图书个数,再依次输出图书信息。
  5. 新近一批图书,插入到图书表中的指定位置,并输出插入后的图书表信息。
  6. 如果图书表中不允许存在书号相同的图书,请为图书表去重,即删除书号相同的图书(只保留一本)。

实验环境: devc++
实现代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
//1.书的结构定义 
typedef struct Book{
	string number;
	string name;
	float price;
}Book;

//2.链表的结构定义,一个数据一个指针 
typedef struct LinkNode{
	Book *data;
	struct LinkNode *next;
	int length;
}LinkNode,*LinkList; 

//3.初始化
//3.1 链表的初始化 
LinkList init_list(){
	LinkList l = new LinkNode;
	l->next = NULL;
	l->length = 0;
	l->data = NULL;
	return l;
} 

//3.2 节点的初始化
LinkNode *init_node(Book *book){
	LinkNode *node = new LinkNode;
	node->data = book;
	node->next = NULL;
	node->length = 1;
	return node;
} 

//3.3 图书的初始化
Book *init_book(string num1,string nam1,float price1){
	Book *boo = new Book;
	boo->number = num1;
	boo->name = nam1;
	boo->price = price1;
	return boo;
} 

//4.图书信息表的创建
void creat_book_list(LinkList &l,int n){
	l->length= n; 
	cout<<"请输入您想要存放的数据:"<<endl;
	//4.1.输入的数据是书这个数据结构的内容
	string number;
	float price;
	string name;
	LinkList r = l;
	for(int i=0;i<n;i++){
		cin>>number;
		cin>>name;
		cin>>price;
//		cout<<number<<" "<<name<<" "<<price<<endl;
		Book *my_book = init_book(number,name,price);	
		//4.2.得到书的数据类型后就可以将其插入到信息表中了
		//4.2.1 初始化节点
		LinkNode *tmp = init_node(my_book);
		if(i == 0){
			r->data = my_book;
		}
		// 4.2.2 尾插法插入元素,没有虚拟头节点 
		else{
			r->next = tmp;
			r = tmp;
		}

	}
	r->next = NULL;

	  
} 

//5.展示链表
void display(LinkList l){
	cout<<"=============== 展示:==============="<<endl;
	int x = 1; 
	while(l){
		cout<<x++<<" ";
		cout<<l->data->number<<" "<<l->data->name<<" "<<l->data->price<<endl;
		l = l->next; 
	} 
	cout<<"=============== over!! ==============="<<endl;
} 

//6.涨价函数 有数据要改 
void add_price(LinkList &l){
	//6.1 计算链表里数据的平均值
	int sum = 0;
	LinkNode *r = l;
	while(r){
		sum += r->data->price;
		r = r->next;
	}

	float average = sum / 10; //****一会这要进行改变****
	//低于平均价格的图书价格涨价10%,高于或等于平均价格的图书价格涨价5%,并输出调价后的图书信息。 
	r = l;
	while(r){
		if(r->data->price < average)
			r->data->price = 1.1 * r->data->price;
			
		else
			r->data->price = 1.05 * r->data->price; 
			
		r = r->next;
	} 
	 
} 

//7.反转链表里的内容
LinkList reverse_real(LinkNode *pre,LinkNode *cur){
	//1.递归结束的最终条件 
	if(cur == NULL) return pre;//cur为null,那它的前一个就说明是原来链表的末尾结点,也就是新链表的头节点,返回新的头节点说明链表反转成功 
	//2.用一个结点来记录当前节点的下一个结点
	LinkNode *tmp = cur->next;
	//3.真正的反转操作,让当前指针指向当前指针的前一个指针,就是链表的反转操作 
	cur->next = pre;
	//4. 上面仅仅只是反转了一次,重新调用反转函数接着向后进行操作
	return reverse_real(cur,tmp);
	/*
	只需假想一下链表反转的情况即可,一开始传入的是(null,head),head表示链表的真正头节点,执行到return之前仅仅只是记录了一下原来
	的head->next指针,并让头部指向了pre也就是null;所以下一步要反转的就是cur和记录下head->next的指针进行反转然后依次...... 
	 
	*/ 
}
void reverse_link(LinkList &l){
	int n = l->length;
	l = reverse_real(NULL,l);
	l->length = n;
	
	// reverse_real(NULL,l) = reverse_real(l,tmp1) = reverse_real(tmp1,tmp2)= ...... = pre ,所以最后 l 得到的就是返回的 头部节点 
} 

//8.在图书中找出最贵的书
void find_most_dear(LinkList l){
	//8.1用于遍历
	LinkNode *r = l->next;  
	//8.2用于记录,因为可能会出现多个值,所以将其设置为链表 ,但实质上和LinkNode * 一致 
	
  //又开辟了一个新的空间用于记录,是为了避免原来的链表收到tmp的影响,只需将l的头部数据赋值给tmp即可,并不是地址 
	LinkList my_list = init_node(l->data);
	
	LinkNode* tmp = my_list; //此时tmp的next为空,说明不是原来的链表了 

	while(r){
//		cout<<tmp->data->price<<" "<< r->data->price <<endl;
		if(tmp->data->price < r->data->price ){
			//8.3如果当前tmp所代表的价格要小于遍历得到的,就更新 
			LinkNode *node = init_node(r->data); //意为创建一块新的内存空间,为了不影响原来的链表, 
			tmp = node;
			my_list = tmp; //表示每次调用if里面时,my_list的头部都会改变 
		}
	
		//8.4如果tmp的价格等于遍历得到的就放到tmp的next指针 
		else if(tmp->data->price == r->data->price){ 
			LinkNode *p = init_node(r->data);
			tmp->next = p;
			tmp->length += 1;
			tmp = p;
			
		}
		//8.5用于控制循环次数 
		r = r->next; 

					
	}
	tmp->next = NULL;
	cout<<"共匹配到"<<my_list->length<<"本价格最高的图书:"<<endl; 
	display(my_list); //对新链表进行展示 

} 

//9.将新来的图书插入到指定位置
int insert_book(LinkList &l,int index,Book *book){
	//9.1 条件判断 
//	cout<<l->length<<endl;
	if(index <= 0 || index > l->length) return -1;
	//9.2 创建链表节点
	LinkNode *my_book = init_node(book);
	//9.3 要插入到指定位置就要 找到要插入位置的前一个结点
	if(index == 0){
		LinkNode *tmp = l;
		l = my_book;
		l->next = tmp;
//		cout<<"222"<<endl;
		
	} 
	else{
//		cout<<"111"<<endl;
	index = index - 1;
	//定义一个结点指向真正的头节点 
	LinkNode *p = l;
	while(index--){
		p = p->next; //循环完成之后,p指的就是要插入位置的前面一个节点 
	}
	my_book ->next = p->next;
	p->next = my_book;
	}

	l->length += 1;
	return 0; 
	
} 

//10.将书号相同的数据进行去重,如果有相同的删去后面的那个
void delete_same_number(LinkList &l){
	LinkNode *r = l;
	LinkNode *inner = l;
	cout<<l->length<<endl;
	while(r){
		//必须加上inner不为空这个条件,因为如果当前inner已经为空就不存在inner->next这条语句,就会报错
		//而如果inner不为空inner->next为空,则下面的比较就没有意义 
		while(inner && inner->next){
//			cout<<r->data->number<<" "<<inner->next->data->number<<endl;
			if(r->data->number == inner->next->data->number){//意为当外循环的序号与内循环的下一个结点的序号相同时就删除内循环的那个结点 
				cout<<"相同编号"<<inner->next->data->number<<"去重成功!!"<<endl; 
				inner->next = inner->next->next;
				l->length -= 1; 
								
			}
			inner = inner->next;//循环变量 

		}
		r = r->next;
		inner = r;
	}

//因为处理了l->length所以不能使用for循环 
//	for(int i=0;i<l->length;i++){//外循环进行遍历		
//		for(int j=i+1;j<l->length;j++){
//			
//			cout<<r->data->number<<" "<<inner->next->data->number<<endl;
//			if(r->data->number == inner->next->data->number){//意为当外循环的序号与内循环的下一个结点的序号相同时就删除内循环的那个结点 
//				cout<<inner->next->data->number<<"去重成功!!"<<endl; 
//				inner->next = inner->next->next;
//				l->length -= 1; 
//								
//			}
//			inner = inner->next;//循环变量 
//		}
//		cout<<"111"<<endl;
//		r = r->next;
//		cout<<r->data->number<<endl;
//	}
} 
 
int main()
{
	LinkList l1 = init_list(); 
	int num = 0; 
	while(1){
		//1.展示功能界面
		cout<<"***欢迎来到图书管理系统***"<<endl;
		cout<<"******1.存入图书信息******"<<endl;
		cout<<"******2.图书进行涨价******"<<endl; 
		cout<<"******3.逆转图书信息******"<<endl;
		cout<<"******4.找出最贵图书******"<<endl;
		cout<<"******5.插入指定图书******"<<endl;
		cout<<"******6.为图书表去重******"<<endl; 
		cout<<"******7.展示当前图表******"<<endl;
		cout<<"**************************"<<endl; 
		cout<<"请输入您想使用的功能编号(输入0退出):"<<endl;
		int answer;
		cin>>answer;
		if(answer == 0)
			break;
		if(answer == 1){
			cout<<"请输入您想要传入图书的个数:"<<endl;
			int n;
			cin>>n; 
			creat_book_list(l1,n);
			cout<<"存入成功!!"<<endl;
			display(l1); 
			num++;
		}
		else if(num == 0){
			cout<<"只有存入图书信息后才能使用该功能!!"<<endl; 
		}
		else if(answer == 2){
			add_price(l1);
			cout<<"涨价成功!!"<<endl; 
			display(l1);
		}
			
		else if(answer == 3) {
			reverse_link(l1);
			cout<<"逆转成功!!"<<endl; 
			display(l1);
		}
		else if(answer == 4){
			find_most_dear(l1);
		}
		else if(answer == 5){
			cout<<"请输入要插入的数据:"<<endl;
			float price;
			string name,number;
			cin>>number>>name>>price;
			Book *boo = init_book(number,name,price);
			cout<<boo->price<<boo->name<<endl;
			cout<<"请输入想要插入的位置(从0开始):"<<endl;
			int ind;
			cin>>ind; 			
			if(insert_book(l1,ind,boo) == 0)
				cout<<"插入成功!!"<<endl; 
			else
				cout<<"插入失败!!"<<endl; 
			display(l1);
		}
		else if(answer == 6){
			delete_same_number(l1);	
			display(l1);
		}
		else if(answer == 7)
			display(l1);
		else
			cout<<"请输入有效数字!!"<<endl; 

}
		                    
	 
	                  
/*
	//测试
	LinkList l1 = init_list();
	creat_book_list(l1,10); 
	display(l1);
	
//	add_price(l1);
//	display(l1);
//	
//	reverse_link(l1);
//	display(l1);
//	
	find_most_dear(l1); 
	display(l1);
	
//	cout<<"请输入要插入的数据:"<<endl;
//	float price;
//	string name,number;
//	cin>>number>>name>>price;
//	Book *boo = init_book(number,name,price);
//	insert_book(l1,1,boo);
//	display(l1); 
//	
//	delete_same_number(l1);
//	display(l1); 

*/ 
	return 0;
}
// over!!
  • 1
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值