链表由一系列节点构成,节点可以在运行中动态生成。使用链表结构能够克服数组链表需要预先知道数据大小的缺点,充分利用计算机内存空间,实现灵活的内存动态管理。
当数据动态生成时,此时我们无法确知其数据大小,当然也无法进行判断了,而链表则可以解决此问题。针对上题文本数据,我们给出链表的解法。
首先,我们要熟悉下链表的创建过程:往链表头部加入新节点。
Node *head =nullptr;
while(...)
{
Node* data=new Node;
//读入数据
//添加链表
data->next = head;
head = data; //存放下个数据的地址
创建了链表之后,遍历链表节点的方法:
int cnt=0;
while (head)
{
cout<<cnt<<" "<<head->id>>ends;
cnt++;
head = head->next;
}
如图,链表结构为:
链表的内存空间需要释放:
while(head)
{
Node* tmp = head;
head = head->next;
delete tmp;
}
由于tmp和head指向统一内存单元,先让head指针指向下一个内存单元,再释放tmp指向的当前内存单元数据。
完整代码如下:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
struct time
{
int year,month,day;
int hour,minute,second;
};
struct Node
{
struct time tm;
char id[20];
char op[10];
Node* next;
};
// 哈希算法:累计异或得到哈希值
int Hash(const char *str)
{
int sum=0;
for(int i=0;i<strlen(str);i++)
sum ^= str[i];
return sum;
}
// 加入哈希链表
void Insert(Node *Hash_tab[],Node elem)
{
//计算每个编号的哈希值
int idx=Hash(elem.id);
//添加新的节点到链表头
Node* data = new Node;
*data=elem;
data->next = Hash_tab[idx];
Hash_tab[idx]=data;
}
// 释放一个链表内存
void Delete(Node* list)
{
while(list)
{
Node* tmp = list;
list=list->next;
delete tmp;
}
}
// 释放全部链表内存
void Release(Node* Hash_tab[])
{
for(int i=0;i<256;i++)
{
if(Hash_tab[i]==nullptr)
continue;
Delete(Hash_tab[i]);
Hash_tab[i]=nullptr;
}
}
// 输出一条哈希链表
void Print(Node* list)
{
while(list)
{
cout<<list->id<<endl;
list=list->next;
}
}
// 输出全部哈希链表
void Output(Node* Hash_tab[])
{
for(int i=0;i<256;i++)
{
if(Hash_tab[i]==nullptr)
continue;
cout<<i<<" : "<<endl;
Print(Hash_tab[i]);
cout<<endl;
}
}
int main(int argc, const char * argv[]) {
//链表指针初始化,不指向任何变量
Node* list_tab[256]={nullptr};
ifstream fin("log.txt");
while(!fin.eof())
{
char tmp;
Node data;
//读入一行数据
fin>>data.tm.year>>tmp>>data.tm.month>>tmp>>data.tm.day;
fin>>data.tm.hour>>tmp>>data.tm.minute>>tmp>>data.tm.second;
fin>>data.id;
fin>>data.op;
//添加至哈希链表
Insert(list_tab,data);
}
fin.close();
//输出哈希链表内容
Output(list_tab);
//释放哈希链表内存
Release(list_tab);
return 0;
}
当数据用二进制文件存取显示时,有如下定义:
读文件 ifstream fin(filename, ios::binary);
写文件 ofstream fout(filename, ios::binary);
数据读取 fin.read((char*)&(data),sizeof(data));
数据写入 fin.write((char*)&(data),sizeof(data));
在之前的基础上,建立一个新的结构体
struct Log_item
{
tm t;
char id[20];
char op[10];
};
struct Node
{
Log_item log;
Node* next;
};
主函数如下:
int main()
{
...//同前面操作
Output(list_tab);
//保存哈希表内容到二进制文件中
SaveHashTab(list_tab,"list.tab");
//释放哈希表内存
Release(list_tab);
//从二进制文件中重新载入哈希表
LoadHashTab(list_tab,"list.tab");
Output(list_tab);
Release(list_tab);
return 0;
}
//保存哈希表内容到二进制文件中
void SaveHashTab(Node* hash_tab[],const char* filename)
{
ofstream fout(filename,ios::binary);
for(int i=0;i<256;i++)
{
Node* p =hash_tab[i];
while(p)
{
fout.write((char*)&(p->log),sizeof(p->log));
p=p->next;
}
fout.close();
}
// 从二进制文件中读取哈希表
void LoadHashTab(Node* hash_tab[],const char* filename)
{
ifstream fin(filename,ios::binary);
while(fin)
{
Node data;
fin.read((char*)&(data->log),sizeof(data->log));
if(fin.eof())
break;
Insert(hash_tab,data);
}
fin.close();
}