📄 list.h
字号:
#ifndef LIST_H
#define LIST_H
#include "bookData.h"
#include "userInfo.h"
#include "readerInfo.h"
#include "dataNode.h"
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#include <conio.h>
//这是一个双向链表类模板
template <class T>
class List
{
dataNode<T> * head; //头指针
dataNode<T> * pre; //前指针
dataNode<T> * cur; //当前指针
long total; //链表中的数据总数
bool atHead(); //判断当前指针是否在链表开头
bool atEnd(); //判断当前指针是否在链表尾
bool curIsEmpty(); //判断当前指针是否指向空
void toHead(); //将当前指针指向链表开头
void advance(); //将当前指针前移1位
dataNode<T> * newNode(const T &);//创建一个新的独立的节点
void insertAfter(const T &); //将数据插入当前指针的后面
void nodeReferenceError(); //提示链表指针出错,结束程序
public:
List(); //构造函数,将对链表进行初始化设置
~List(); //析构函数。释放空间,并打开特定文件,将数据重新写入,确保了将每次更新自动存入文件
bool listIsEmpty(); //判断链表是否为空,是返回TRUE,否则返回FALSE
long getTotal(); //返回链表中的数据总数
dataNode<T> * creatList(fstream &); //创建链表,返回创建后的链表头指针,其参数为其进行初始化的数据来源
void insert(const T &); //将数据插入当前指针的前面
bool deleteNode(char s[]); //接收一个CHAR []进行查询,找到后将数据在链表中删除,并返回TRUE,否则返回FALSE
bool search(char s[]); //接收一个CHAR []检索信息,查到返回TRUE,否则返回FALSE
void compositor(); //按各数据重载的>进行判断排序
T& returnCurData(); //返回当前数据
dataNode<T> * returnCurPtr(); //返回当前指针,以便修改当前数据
void displayAllData(); //显示所有数据
};
//**********************************************************************************
//类实现部分
//**********************************************************************************
template <class T>
List<T>::List()
{
head = NULL;
pre = NULL;
cur = NULL;
total = 0;
}
//**********************************************************************************
//析构LIST对象。打开特定文件,将数据重新写入,确保了将每次更新自动存入文件
//此函数中用IF语句进行判断打开文件的顺序不能变,因为主程序中对对象析构有顺序要求
template <class T>
List<T>::~List()
{
fstream file;
if(USERFILE == true) //根据标志打开指定文件
{
file.open("userInfo.txt",ios::out|ios::binary);
USERFILE = false;
}
else if(READERFILE == true) //根据标志打开指定文件
{
file.open("readerInfo.txt",ios::out|ios::binary);
READERFILE = false;
}
else if(BOOKFILE == true) //根据标志打开指定文件
{
file.open("bookDatas.txt",ios::out|ios::binary);
BOOKFILE = false;
}
else
{
cout<<"析构函数打开文件时出错!"<<endl;
return;
}
if(!file)
{
cout<<"bookDatas文件打开失败!";
exit(0);
}
//打开文件(清空旧数据),重新写入,并释放当前对象所有指针
if(listIsEmpty()) //判断链表是否为空
{
total = 0;
return;
}
else
{
toHead();
while(!atEnd())
{
file<<returnCurData(); //重写数据
advance();
}
file<<returnCurData()<<endl;
file.close();
//释放当前对象所有指针
toHead(); //回到链表头
advance(); //将当前指针前移1位
while(!atEnd())
{
delete pre;
advance();
}
if(pre != NULL)//可能有时pre是指向空的
delete pre;
delete cur;
}
total = 0; //将总数清0
}
//**********************************************************************************
//返回链表中数据总数
template <class T>
long List<T>::getTotal()
{
return total;
}
//**********************************************************************************
//判断当前指针是否在链表开头
template <class T>
bool List<T>::atHead()
{
return cur == head;
}
//**********************************************************************************
//判断当前指针是否在链表尾
template <class T>
bool List<T>::atEnd()
{
if(cur->next == NULL)
return true;
else
return false;
}
//**********************************************************************************
//判断链表是否为空,是返回TRUE,否则返回FALSE
template <class T>
bool List<T>::listIsEmpty()
{
if(head == NULL)
return true;
else
return false;
}
//**********************************************************************************
//判断当前指针是否指向空
template <class T>
bool List<T>::curIsEmpty()
{
if(cur == NULL)
return true;
else
return false;
}
//**********************************************************************************
//将当前指针指向链表开头
template <class T>
void List<T>::toHead()
{
pre = NULL;
cur = head;
}
//**********************************************************************************
//将当前指针前移1位,将在最后一个数据上停止
template <class T>
void List<T>::advance()
{
if(!atEnd())
{
pre = cur;
cur = cur->next;
}
}
//**********************************************************************************
//创建一个新的独立的节点
template <class T>
dataNode<T> * List<T>::newNode(const T &obj)
{
dataNode<T> * ptr = new dataNode<T>; // T yao ma?
ptr->data = obj;
ptr->next = NULL;
return ptr;
}
//**********************************************************************************
//提示链表指针出错,结束程序
template <class T>
void List<T>::nodeReferenceError()
{
cout<<"当前没有节点或是不合理的节点,即将结束程序!"<<endl;
cout<<"按任意键继续.........."<<endl<<endl;
getch();
exit(0);
}
//**********************************************************************************
//创建链表,返回创建后的链表头指针,其参数为其进行初始化的数据来源
template <class T>
dataNode<T> * List<T>::creatList(fstream &file)
{
T temp;
head = NULL;
pre = NULL;
cur = NULL;
total = 0;
file>>temp; //从文件读入数据
while(!file.eof())
{
insertAfter(temp);
file>>temp;
//cout<<file.tellg()<<endl; //调试用,以后要删掉
}
toHead();
return cur;
}
//**********************************************************************************
//将数据插入当前指针的前面
template <class T>
void List<T>::insert(const T &obj)
{
dataNode<T> * temp = newNode(obj);//为参数申请一个新的节点
if(listIsEmpty()) //链表为空时
{
head = temp;
cur = temp;
pre = NULL;
}
else if(curIsEmpty()) //当前指针为空时
{
nodeReferenceError();
}
else if(atHead()) //当前指针在头节点时
{
temp->next = cur;
head = temp;
cur = temp;
}
else //其余情况
{
temp->next = cur;
pre->next = temp;
cur = temp;
}
cout<<"插入成功!"<<endl;
total++; //计数
}
//**********************************************************************************
//将数据插入当前指针的后面
template <class T>
void List<T>::insertAfter(const T &obj)
{
dataNode<T> * temp = newNode(obj);
if(listIsEmpty()) //链表为空时
{
head = temp;
cur = temp;
pre = NULL;
}
else if(curIsEmpty()) //当前指针为空时
{
nodeReferenceError();
}
else //其余情况
{
pre = cur;
temp->next = cur->next;
cur->next = temp;
cur = temp;
}
total++; //计数
}
//**********************************************************************************
//LIST类的deleteNode(CHAR [])接收一个CHAR []进行查询,找到后将数据在
//链表中删除,并返回TRUE,否则返回FALSE
template <class T>
bool List<T>::deleteNode(char goal[])
{
bool sign = false;
dataNode<T> * temp = NULL; //为了释放被删除的指针
if(!search(goal))
{
cout<<"没有查到数据。"<<endl;
return sign;
}
else if(atHead())
{
if(cur->next == NULL ) //链表中只有一个数据,且为所查找的数据
{
delete cur;
head = NULL;
cur = NULL;
pre = NULL;
}
else
{
head = cur->next;
delete cur;
cur = head;
}
}
else if(atEnd()) //在链表尾时
{
pre->next = NULL;
delete cur;
toHead(); //如果要删除的数据在末尾,CUR将指向HEAD;
}
else //其余情况
{
temp = NULL;
delete cur;
cur = temp;
pre->next = cur;
}
total--; //计数
sign = true;
return sign;
}
//**********************************************************************************
//接收一个CHAR []检索信息,查到返回TRUE,否则返回FALSE
template <class T>
bool List<T>::search(char goal[])
{
toHead(); //回到链表头
if(listIsEmpty())
{
cout<<"链表为空,没有要搜索的数据。"<<endl;
return false;
}
while(!atEnd())
{
if(cur->data == goal) //==号已重载
return true;
advance();
}
if(cur->data == goal) //==号已重载
return true;
return false;
}
//**********************************************************************************
//返回当前数据
template <class T>
T& List<T>::returnCurData()
{
return cur->data;
}
//**********************************************************************************
//返回当前指针,以便修改当前数据
template <class T>
dataNode<T> * List<T>::returnCurPtr()
{
return cur;
}
//**********************************************************************************
//按各数据重载的>进行判断排序
template <class T>
void List<T>::compositor()
{
dataNode<T> * temp = NULL;
long count;
toHead();
if(listIsEmpty())
{
cout<<"目前没有数据!"<<endl;
return;
}
else if(cur->next == NULL)
{
return;
}
else if((cur->next)->next ==NULL)
{
if(cur->data > (cur->next)->data) //>号已重载
{
head = head->next;
head->next = cur;
cur->next = NULL;
cur = head;
}
}
else
for(count = 0;count <= total;count++) //冒泡排序,>号已重载
{
toHead();
if(cur->data > (cur->next)->data)
{
head = head->next;
temp = head->next;
head->next = cur;
cur->next = temp;
cur = head;
}
advance();
while(!atEnd())
{
if(cur->data > (cur->next)->data) //>号已重载
{
temp = cur;
pre->next = cur->next;
cur->next = (cur->next)->next;
(pre->next)->next = temp;
cur = pre->next;
}
advance();
}
}
}
//**********************************************************************************
//显示所有数据
template <class T>
void List<T>::displayAllData()
{
int count = 1;
if(listIsEmpty())
{
cout<<"目前没有数据!"<<endl;
return;
}
else
{
toHead();
for(;!atEnd();count++)
{
cout<<returnCurData()<<endl;
advance();
if(!(count %= 20)) //如果数据超过20个则分页显示
{
cout<<"按任意键继续显示下一页............"<<endl;
getch();
}
}
cout<<returnCurData()<<endl;
}
}
//**********************************************************************************
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -