【数据结构之线性表】单链表实现图书管理系统

        本次实验是在DEV C++软件上进行实现的。语言采用的是c++语言,但在整体上与c语言大致相似(不管用什么语言实现,思想是不变的)。

        此次实现的整体思路:首先定义图书这个抽象数据类型,并且定义节点抽象数据类型(根据这些抽象数据类型对下面的数据进行定义)。然后进行单链表的初始化、单链表的取值、单链表的查找、单链表的插入、单链表的删除、尾插法建立单链表。在尾插法建立单链表时使用了文件流读取txt文件,并将其存储到链表中。最后建立主函数,使用主函数调用上述的算法。

        具体程序代码如下:

#include<iostream>
#include<fstream>
#include <iomanip>
typedef int Status; 
using namespace std;
struct Book {
	string id;//ISBN
	string name;//书名
	double price;//价格 
};
typedef struct LNode {
	Book data;//节点数据
	struct LNode *next;//节点指针域 
} LNode, *LinkList;//都是LNode的别名,其中LinkList 为指向结构体LNode的指针类型
//单链表的初始化
Status InitList (LinkList &L) {
	//构建一个空链表
	L = new LNode;//生成新节点作为头节点,头指针L指向头结点
	L->next = NULL;//头指针指针域置空。 
	return 1; //初始化成功返回1. 
}
// 单链表的取值
Status GetElem (LinkList L, int i, Book &e) {
	//在带头节点的单链表L中查找第i个元素,并赋值给e
	LNode *p;
	int j;
	p = L->next;//初始化,p指向首元节点,计数器初值赋值为1. 
	j = 1;
	while (p && j < i) {//顺着链表往下找,直到p为空或者p指向第i个元素。 
		p = p->next;
		++j;
	}
	if(!p || j > i) {
		cout << "i值不合法。";
		return 0;
	} 
	e = p->data;//将*P节点的数据赋值给e。 
	return 1;//取值成功返回1. 
} 
//单链表的查找
Status LocateElem (LinkList L,double e) {
	//在带头结点的单链表L中查找值为e的元素。 
	LNode *p;
	int j = 1;
	p = L->next;//初始化,指针p指向首元节点 
	while (p && p->data.price != e) {//顺着链表向下查找,直到p为空,或者p所指的数据域等于e。 
		p = p->next;
		++j;
	}
	return j;//查找成功返回e的节点地址p,失败则返回NULL。 
} 
//单链表的插入
Status ListInsert (LinkList &L,int i, Book &e) {
	LNode * p, * s;
	int j = 0;
	p = L;
	while (p && j < i -1) {//查找第i-1个元素节点,p指向该节点。 
		p = p->next;
		++j;
	} 
	if(!p || j > i - 1) {
		cout << "i值不合法!!!";
		return 0;
	}
	s = new LNode;//生成新节点*s。 
	s->data = e;//将新节点的数据域置为e。 
	s->next = p->next;//将节点*s的指针域指向第i个元素。 
	p->next = s;//将节点*p的指针域指向*s的指针域。 
	return 1;//插入成功返回1. 
} 
//单链表的删除
Status ListDelete (LinkList &L, int i) {
	LNode *p, *q;
	p = L;
	int j = 0;
	while (p->next && j < i - 1) {//查找第i-1个节点,p指向第i-1个位置。 
		p = p->next;
		++j;
	}
	if(!(p->next) || j > i - 1) {
		cout << "i值不合法,删除失败!!!";
	} 
	q = p->next;//临时保存被删除节点的地址以备释放。
	p->next = q->next;//改变删除节点前驱结点的指针域。
	delete q;
	return 1;//删除成功返回1. 
} 
//使用尾插法创建单链表
void CreateList (LinkList &L, int n) {
	LinkList p,r;
	string head_1,head_2,head_3;
	L = new LNode;
	L->next = NULL;//先建立一个带头结点的空链表。
	r = L;//尾指针r指向头结点
	int length = 0;
	fstream file;
	file.open("book.txt");
	if(!file) {
		cout << "未找到相关文件,无法打开!!!" <<endl;
		exit(0);
	} 
	file >> head_1 >> head_2 >> head_3;
	while (!file.eof()) {//蒋文件中的信息运用尾插法插入到链表中。 
		p = new LNode;//生成新节点。
		file >> p->data.id >> p->data.name >> p->data.price;//输入元素赋值给新节点的数据域。
		p->next = NULL;
		r->next = p;//新节点*p插入到尾结点*r之后。
		r = p;//r指向新的尾结点*p 
		length++;//同时对链表的长度进行统计 
	}
	file.close(); 
} 
//构建主函数,调用上述算法
 int main() {
 	int i = 0, n = 0, choose,length = 0;
 	double price;
 	Book e;
 	LinkList L,p;
 	choose = -1;
	cout << "1,建立\n";
 	cout << "2,输入\n";
 	cout << "3,取值\n";
 	cout << "4,查找\n";
 	cout << "5,插入\n";
 	cout << "6,删除\n";
 	cout << "7,输出\n";
 	cout << "8,退出\n";
 	while (choose != 0) {
	 	cout << "请选择:\n";
	 	cin >> choose;
	 	switch (choose) {
	 		case 1://建立单链表。
			 	{
			 		if(InitList(L)) {
			 		cout << "成功建立链表!\n";
					 }
		 			break;
				 }
	 		case 2://使用尾插法创建单链表。
			 	{
			 		CreateList (L,length); 
			 	  	cout << "输入book.txt 信息完毕\n";
				 }
			 	break;
			case 3://单链表的按序号取值,
				   //调用函数:Status GetElem (LinkList L, int i, Book &e)
				{
					cout << "请输入序号:\n";
					cin >> i;
					GetElem(L,i,e);//调用单链表的取值函数。 
					cout << "序号为" << i << "的图书信息为:\n";
					cout << e.id << "\t\t" << e.name << "\t\t"<<e.price;
				}
				break; 
			case 4://单链表的查找,调用函数:
				   // Status LocateElem (LinkList L,double e)
				{
					price = 0;
					cout << "请输入查找的价格;";
					cin >> price;
					n = LocateElem(L,price);
					cout << "第一个出现该价格的图书序号为:";
					cout << n;
				}
				break;
			case 5://单链表的插入,调用函数:
			       // Status ListInsert (LinkList &L,int i, Book &e)
			    {
			    	cout << "请输入插入的位置,和图书信息(编号、书名、价格):";
				    cin >> i >> e.id >> e.name >> e.price;
				    if(ListInsert(L,i,e)) {
				    	cout << "插入成功!!!";
					}
				}
				break;
			case 6://单链表的删除,调用函数:
				   // Status ListDelete (LinkList &L, int i)
				{
					cout << "请输入所要删除图书的序号:\n";
					cin >> i;
					if(ListDelete(L,i)) {
						cout << "删除成功!!!";
					}
				}
				break;
			case 7://单链表的输出
				{
					cout << "当前图书系统信息(链表)读出:\n";
					p = L->next;//节点*p指向链表的首元节点。 
					while (p) {
						cout << left << setw(15) << p->data.id <<
						left << setw(50)<<p->data.name <<left<<setw(5)
						<<p->data.price<<endl;
						p=p->next;
					} 
					cout <<endl;
				}
				break;
			case 8:
				choose = 0;
				break;
			default:
				break; 
		 }
	 }
	 return 0;
 }

程序中用到的book.txt文件:

链接:https://pan.baidu.com/s/1RZm-5azt7Qu4JMD2Ll_HFw?pwd=tfr2 

  • 19
    点赞
  • 158
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值