用c语言实现简单的哈希表,电影进行分类。
头文件
#pragma once
#include<string.h>
#include<time.h>
#include<iostream>
#include<vector>
using namespace std;
//影片信息
typedef struct Film
{
string FilmName;
float score;//评分
string AwardType;//获得奖项
string FilmmakingState;//制片国家
string Director;//导演
string Performer;//演员列表
string Type;//电影类别
string BriefIntroduction;//简介
string ReleaseTime;//上映时间
int Clicks;//点击量
string link;//链接
Film()
{
memset(this, 0, sizeof(struct Film));//构造函数,初始化,清空内存;
}
}Film;
//将时间字符串转化成time_t
time_t StrinToTime(string str_Time);
//单链表,存储从文件读取的电影的信息
//链表节点
typedef struct FilmNode
{
int Number;//节点数
Film* FilmInfo;//电影信息
struct FilmNode * next;//指向后继
}Node;
//比较大小时用的结构体
typedef struct SortNode
{
Node *pNode;//保存地址
int Clicks;//点击量
}SortNode;
typedef struct SortNodee
{
Node *pNode;//保存地址
time_t ReleaseTime;//上映时间
}SortNodee;
typedef struct SortNodeee
{
Node *pNode;//保存地址
float flag;//评分
}SortNodeee;
//哈希节点
typedef struct HashLeafNode
{
Node *pNode;//保存地址
struct HashLeafNode *next;
}HashLeafNode;
//哈希表头
typedef struct HashNode
{
string key;//键值
HashLeafNode *LeafNode;//指向孩子节点
struct HashNode *next;
HashNode()
{
memset(this, 0, sizeof(HashNode));
}
}HashNode;
//创建链表,返回头结点
Node* Creatlist();
//插入节点,尾插
bool InsertNod(Node* Head, Node* NewNode);
//电影名查找
SortNode* Find(Node* Head, string name);
把点击量和平份和节点地址放入数组
void ArrForList(Node*Head, SortNode **ArrHead, SortNodee **ArrHeade, SortNodeee **ArrHeadeee);
//按照点击量和评分排序(冒泡排序)
void sortForArr(void *ArrHard, int flag,int size);
//节点交换位置
void NodSwp(void *Node1, void *Node2, int size);
//简易的哈表
HashNode *CreatHashTab();
//给哈希表添加节点
bool InsertHashNod(string Key, HashNode * HashHead, HashLeafNode* LeafNode);
//读Excel表,读影片信息
void ReadMovInfo(Node* Head);
//中文的内容读出来后要进行编码的转换,这个为转换函数:wchar_t to char
char *w2c(char *pcstr, const wchar_t *pwstr, size_t len);
//按奖项分类
void ClassificationOfAwards(HashNode * Head, Node* HeadList,int flag);
//字符串拆分
void SplitStr(string str, int flag, vector<string>& Temp);
源文件,插入节点是用的了第三方库libxl读取Excel表的文件内容读取,将字段保存在结构体中
#include"libxlwin\libxlwin\libxl-3.6.5.0\include_cpp\libxl.h"
#include"Movies.h"
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
time_t StrinToTime(string str_Time)//2018-09-07
{
char *str = (char*)str_Time.data(); // 将string转换成char*。
tm tm_; // 定义tm结构体。
int year, month, day;// 定义时间的各个int临时变量。
sscanf_s(str, "%d-%d-%d", &year, &month, &day);// 将str存储的日期时间,转换为int临时变量。
tm_.tm_year = year - 1900; // 年,由于tm结构体存储的是从1900年开始的时间,所以tm_year为int临时变量减去1900。
tm_.tm_mon = month - 1; // 月,由于tm结构体的月份存储范围为0-11,所以tm_mon为int临时变量减去1。
tm_.tm_mday = day; // 日。
tm_.tm_hour = 0; // 时。
tm_.tm_min = 0; // 分。
tm_.tm_sec = 0; // 秒。
tm_.tm_isdst = 0; // 非夏令时。
time_t t_ = mktime(&tm_); // 将tm结构体转换成time_t格式。
return t_; // 返回值。
}
//创建链表,返回头结点
Node* Creatlist()
{
Node* HeadList = new Node();
HeadList->next = NULL;
return HeadList;
}
//插入节点,尾插
bool InsertNod(Node* Head, Node* NewNode)
{
if (NULL == Head || NULL == NewNode)
{
return false;
}
//找到尾节点,插入
Node* Temp = Head;
while (Temp->next)
{
Temp = Temp->next;//指针后移
}
Temp->next = NewNode;
NewNode->next = NULL;
Head->Number += 1;
return true;
}
//把点击量和平份和节点地址放入数组
void ArrForList(Node*Head, SortNode **ArrHead, SortNodee **ArrHeade, SortNodeee **ArrHeadeee)//flag代表按照那种方式来进行排序
{
SortNode *FristNode = new SortNode[Head->Number];
SortNodee *FristNodee = new SortNodee[Head->Number];
SortNodeee *FristNodeee = new SortNodeee[Head->Number];
Node* Temp = Head->next;
int loop = 0;
while (Temp)
{
FristNode[loop].Clicks = Temp->FilmInfo->Clicks;
FristNode[loop].pNode = Temp;
FristNodee[loop].ReleaseTime = StrinToTime(Temp->FilmInfo->ReleaseTime);
FristNodee[loop].pNode = Temp;
FristNodeee[loop].flag = Temp->FilmInfo->score;
FristNodeee[loop].pNode = Temp;
Temp = Temp->next;
loop++;
}
*ArrHead = FristNode;
*ArrHeade = FristNodee;
*ArrHeadeee = FristNodeee;
}
//按照点击量和评分排序(冒泡排序)
void sortForArr(void *ArrHard, int flag, int size)
{
SortNode *FristNode = NULL;
SortNodee *FristNodee = NULL;
SortNodeee *FristNodeee = NULL;
if (1 == flag)
{
FristNode = (SortNode *)ArrHard;
}
else if (2 == flag)
{
FristNodee = (SortNodee *)ArrHard;
}
else if (3 == flag)
{
FristNodeee = (SortNodeee *)ArrHard;
}
else
{
}
for (int j = 0; j < size - 1; j++)
{
for (int i = 0; i < size - 1 - j; i++)
{
if (FristNodee)
{
if (FristNodee[i].ReleaseTime <= FristNodee[i + 1].ReleaseTime)
{
NodSwp(&FristNodee[i], &FristNodee[i + 1], sizeof(SortNodee));
}
}
else if (FristNode)
{
if (FristNode[i].Clicks >= FristNode[i + 1].Clicks)
{
NodSwp(&FristNode[i], &FristNode[i + 1], sizeof(SortNode));
}
}
else if (FristNodeee)
{
if (FristNodeee[i].flag <= FristNodeee[i + 1].flag)
{
SortNodeee * t = &FristNodeee[i];
SortNodeee * t1 = &FristNodeee[i+1];
NodSwp(&FristNodeee[i], &FristNodeee[i + 1], sizeof(SortNodeee));
}
}
}
}
}
//节点交换位置
void NodSwp(void *Node1, void *Node2, int size)
{
void*temp = (void *)malloc(size);
if (NULL == temp)
{
return;
}
memcpy(temp, Node1, size);
memcpy(Node1, Node2, size);
memcpy(Node2, temp, size);
free(temp);
temp = NULL;
}
//简易的哈表
HashNode *CreatHashTab()
{
HashNode *HashHead = (HashNode *)malloc(sizeof(HashNode));
if (HashHead)
{
/*HashHead->LeafNode = NULL;
HashHead->next = NULL;
HashHead->key = "1";*/
memset(HashHead, 0, sizeof(HashNode));
return HashHead;
}
else
{
return NULL;
}
}
//给哈希表添加节点
bool InsertHashNod(string Key, HashNode * HashHead, HashLeafNode* LeafNode)
{
if (NULL == HashHead || NULL == LeafNode)
{
return false;
}
HashNode *Temp = HashHead;
while (Temp)
{
if (Temp->key == Key)
{
LeafNode->next = Temp->LeafNode;//头插
Temp->LeafNode = LeafNode;
return true;
}
Temp = Temp->next;
}
HashNode * NewNod = new HashNode();
if (NULL == NewNod)
{
return false;
}
NewNod->key = Key;
NewNod->LeafNode = LeafNode;
NewNod->next = HashHead->next;
HashHead->next = NewNod;
//=
return true;
}
//中文的内容读出来后要进行编码的转换,这个为转换函数:wchar_t to char
char *w2c(char *pcstr, const wchar_t *pwstr, size_t len)
{
int nlength = wcslen(pwstr);
//获取转换后的长度
int nbytes = WideCharToMultiByte(0, 0, pwstr, nlength, NULL, 0, NULL, NULL);
if (nbytes>len) nbytes = len;
// 通过以上得到的结果,转换unicode 字符为ascii 字符
WideCharToMultiByte(0, 0, pwstr, nlength, pcstr, nbytes, NULL, NULL);
return pcstr;
}
using namespace libxl;
//读Excel表,读影片信息
void ReadMovInfo(Node* Head)
{
Book* book = xlCreateXMLBook();
book->setKey(L"Halil Kural", L"**********************");
if (book->load(L"myMoviesIfo.xlsx"))
{
//从exce中读取球队消息
Sheet * sheet1 = book->getSheet(0);
if (sheet1)
{
for (int loop = 1; loop < 100; loop++)
{
Film *MITemp = new Film();
for (int looT = 0; looT < sheet1->lastCol(); looT++)
{
const wchar_t * t = sheet1->readStr(loop, looT);
if (NULL == t)
{
break;
}
char *pcstr = (char *)malloc(sizeof(char)*(2 * wcslen(t) + 1));
memset(pcstr, 0, 2 * wcslen(t) + 1);
w2c(pcstr, t, 2 * wcslen(t) + 1);
if (0 == looT)
MITemp->FilmName = pcstr;
if (1 == looT)
MITemp->score = atof(pcstr);
if (2 == looT)
MITemp->AwardType = pcstr;
if (3 == looT)
MITemp->Type = pcstr;
if (4 == looT)
MITemp->Director = pcstr;
if (5 == looT)
MITemp->Performer = pcstr;
if (6 == looT)
MITemp->FilmmakingState = pcstr;
if (7 == looT)
MITemp->BriefIntroduction = pcstr;
if (8 == looT)
MITemp->ReleaseTime = pcstr;
if (9 == looT)
MITemp->link = pcstr;
free(pcstr);
pcstr = NULL;
}
Node *Temp = new Node();
Temp->FilmInfo = MITemp;
InsertNod(Head, Temp);
}
}
}
}
//按奖项分类
void ClassificationOfAwards(HashNode * Head, Node* HeadList, int flag)
{
if (NULL == Head || NULL == HeadList)
{
return;
}
vector<string> Temp;
Node*TempHeadList = HeadList->next;
HashNode * TempHead = Head;
while (TempHeadList)
{
switch (flag)
{
case 1:
{
HashLeafNode* LeafNode = new HashLeafNode();
LeafNode->next = NULL;
LeafNode->pNode = TempHeadList;
InsertHashNod(TempHeadList->FilmInfo->Director, Head, LeafNode);
}
break;
case 2:
{
SplitStr(TempHeadList->FilmInfo->AwardType, 1, Temp);
for (int loop = 0; loop < Temp.size(); loop++)
{
HashLeafNode* LeafNode = new HashLeafNode();
LeafNode->next = NULL;
LeafNode->pNode = TempHeadList;
TempHeadList->FilmInfo->AwardType = Temp.at(loop);
InsertHashNod(Temp.at(loop), Head, LeafNode);
}
}
break;
case 3:
{
SplitStr(TempHeadList->FilmInfo->Type, 2, Temp);
for (int loop = 0; loop < Temp.size(); loop++)
{
HashLeafNode* LeafNode = new HashLeafNode();
LeafNode->next = NULL;
LeafNode->pNode = TempHeadList;
InsertHashNod(Temp.at(loop), Head, LeafNode);
}
}
break;
case 4:
{
SplitStr(TempHeadList->FilmInfo->FilmmakingState, 3, Temp);
for (int loop = 0; loop < Temp.size(); loop++)
{
HashLeafNode* LeafNode = new HashLeafNode();
LeafNode->next = NULL;
LeafNode->pNode = TempHeadList;
InsertHashNod(Temp.at(loop), Head, LeafNode);
}
}
break;
default:
break;
}
TempHeadList = TempHeadList->next;
vector<string>().swap(Temp);
}
}
//字符串拆分
void SplitStr(string str, int flag, vector<string>& Temp)
{
switch (flag)
{
case 1:
if (string::npos == str.find_first_of("("))
{
Temp.push_back(str);
}
else
{
Temp.push_back(str.substr(0, str.find_first_of("(") - 1));
}
break;
case 2:
{
string c = ";";
string::size_type pos1, pos2;
pos2 = str.find(";");
pos1 = 0;
while (string::npos != pos2)
{
Temp.push_back(str.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = str.find(c, pos1);
}
if (pos1 != str.length())
Temp.push_back(str.substr(pos1));
}
break;
case 3:
{
string c = "/";
string::size_type pos1, pos2;
pos2 = str.find("/");
pos1 = 0;
while (string::npos != pos2)
{
Temp.push_back(str.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = str.find(c, pos1);
}
if (pos1 != str.length())
Temp.push_back(str.substr(pos1));
}
default:
break;
}
}
//电影名查找
SortNode* Find(Node* Head, string name)
{
Node* Temp = Head->next;
while (Temp->next)
{
if (string::npos != Temp->FilmInfo->FilmName.find(name))
{
SortNode* G = new SortNode();
G->pNode = Temp;
return G;
}
Temp = Temp->next;//指针后移
}
return NULL;
}
保存电影信息的Excel文件