Link.c,RUN
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
线性表:
1.链表
2.插入,删除
3.排序
4.使用函数指针进行不同排序,不同查找的简化
5.将文件和标准输入输出统一
*/
struct Info
{
char name[16];
int value;
};
//typedef的用法,让类型本身有描述性
typedef struct Info MyType;
//以下用MyType类型,这样更换MyType类型时,后续代码不用大的变化!
//函数类型定义,MyTypeFun为排序,查找等函数的原型
typedef int (*MyTypeFun)(const MyType* v1, const MyType* v2);
//链表节点
struct MyTypeNode
{
MyType data;
struct MyTypeNode* next;
};
const MAX_LEN = 1024 * 16; //链表节点最大分配数目
//链表,第一个节点为表头,数据从head->next开始(如果非空)
struct MyLinkList
{
struct MyTypeNode head;
struct MyTypeNode* Tail;
};
//初始化以及清除
void InitLinkList(struct MyLinkList* linkList);
void EmptyLinkList(struct MyLinkList* linkList);
int LinkListIsEmpty(const struct MyLinkList* linkList);
int LinkListIsFull(const struct MyLinkList* linkList);
int LinkListCount(const struct MyLinkList* linkList);
//输入输出
void InputLinkList_(struct MyLinkList* linkList, int n, FILE* fp);
void InputLinkList(struct MyLinkList* linkList);
void LoadLinkList(struct MyLinkList* myList, const char* filename);
void SaveList_(const struct MyLinkList* linkList, FILE* fp);
void PrintLinkList(const struct MyLinkList* linkList);
void SaveLinkList(const struct MyLinkList* linkLis, const char* filename);
//插入删除
void PushBack(struct MyLinkList* linkList, MyType data);
void Remove(struct MyLinkList* linkList, MyType data, MyTypeFun fun);
void Remove_Name(struct MyLinkList* linkList, const char* name);
void Remove_Value(struct MyLinkList* linkList, int value);
//排序
void SortBubble(struct MyLinkList* linkList, MyTypeFun fun);
void SortBubble_NameGreate(struct MyLinkList* linkList);
void SortBubble_ValueLess(struct MyLinkList* linkList);
//查找
MyType* Find_Value(struct MyLinkList* linkList, int data);
MyType* Find_Name(struct MyLinkList* linkList, const char* data);
MyType* Find(struct MyLinkList* linkList, MyType data, MyTypeFun fun);
//测试键盘读入数据
void Test_Input()
{
struct MyLinkList mylist;
InitLinkList(&mylist);
InputLinkList(&mylist);
PrintLinkList(&mylist);
EmptyLinkList(&mylist);
}
//测试文件种读入数据
void Test_Load()
{
struct MyLinkList mylist;
InitLinkList(&mylist);
LoadLinkList(&mylist, "test.txt");
PrintLinkList(&mylist);
EmptyLinkList(&mylist);
}
int main()
{
struct MyLinkList mylist;
InitLinkList(&mylist);
//链表添加一些随机数据
for (int i = 0; i < 10; i++)
{
struct Info info;
sprintf(info.name, "No%d", i);
info.value = rand() % 100;
PushBack(&mylist, info);
}
PrintLinkList(&mylist);
//按照name排序
SortBubble_NameGreate(&mylist);
PrintLinkList(&mylist);
//把value==2的结点删除
Remove_Value(&mylist, 2);
PrintLinkList(&mylist);
//保存到文件
SaveLinkList(&mylist, "test.txt");
EmptyLinkList(&mylist);
return 0;
}
//初始化链表
void InitLinkList(struct MyLinkList* linkList)
{
linkList->head.next = NULL;
linkList->Tail = &linkList->head;
}
//清除链表内存
void EmptyLinkList(struct MyLinkList* linkList)
{
struct MyTypeNode* node = linkList->head.next;
while (node)
{
struct MyTypeNode* temp = node;
node = node->next;
free(temp);
}
}
int LinkListIsEmpty(const struct MyLinkList* linkList)
{
if (linkList->head.next == 0)
return 1;
return 0;
}
int LinkListIsFull(const struct MyLinkList* linkList)
{
int n = LinkListCount(linkList);
if (n < MAX_LEN)
return 0;
return 1;
}
int LinkListCount(const struct MyLinkList* linkList)
{
int count = 0;
const struct MyTypeNode* node = &linkList->head;
while (node->next)
{
node = node->next;
count++;
}
return count;
}
//保存,文件句柄
void SaveList_(const struct MyLinkList* linkList, FILE* fp)
{
const struct MyTypeNode* node = linkList->head.next;
while (node)
{
fprintf(fp, "%s,%d\t", node->data.name, node->data.value);
node = node->next;
}
fprintf(fp, "\n");
}
//输出到屏幕
void PrintLinkList(const struct MyLinkList* linkLis)
{
SaveList_(linkLis, stdout);
}
//保存到文件
void SaveLinkList(const struct MyLinkList* linkLis, const char* filename)
{
FILE* fp = fopen(filename, "W+t");
//可以加上表头
SaveList_(linkLis, fp);
fclose(fp);
}
//输入,文件句柄
void InputLinkList_(struct MyLinkList* linkList, int n, FILE* fp)
{
int cnt;
for (int i = 0; i < n; i++)
{
MyType info;
cnt = fscanf(fp, "%s", info.name);
//fscanf_s(fp, "%s", info.name, 16); //或者
cnt = fscanf(fp, "%d", &info.value);
PushBack(linkList, info);
}
}
//键盘输入
void InputLinkList(struct MyLinkList* linkList)
{
int cnt;
int n;
cnt = scanf("%d", &n);
InputLinkList_(linkList, n, stdin);
}
//文件读入
void LoadLinkList(struct MyLinkList* linkList, const char* filename)
{
FILE* fp = fopen(filename, "rt");
int n = 0;
//表头部分,如果存在
//数据部分
while (!feof(fp))
{
n++;
char temp[2048];
fgets(temp, 2048, fp);
}
rewind(fp); //回到文件开始
//表头部分,如果存在
//数据部分
InputLinkList_(linkList, n, fp);
fclose(fp);
}
//链表尾部插入数据
void PushBack(struct MyLinkList* linkList, MyType data)
{
if (LinkListIsFull(linkList)) return;
struct MyTypeNode* node = (struct MyTypeNode*)malloc(sizeof(struct MyTypeNode));
if (node)
{
node->data = data;
node->next = NULL;
}
linkList->Tail->next = node;
linkList->Tail = node;
}
//定义相等
int Equal(const MyType *v1, const MyType *v2)
{
if (strcmp(v1->name, v2->name) == 0 && v1->value == v2->value)
return 1;
return 0;
}
//定义name相等
int Equal_Name(const MyType* v1, const MyType* v2)
{
if (strcmp(v1->name, v2->name) == 0)
return 1;
return 0;
}
//定义Value相等的函数
int Equal_Value(const MyType* v1, const MyType* v2)
{
if (v1->value == v2->value)
return 1;
return 0;
}
//根据给定的比较函数,删除data
void Remove(struct MyLinkList* linkList, MyType data, MyTypeFun fun)
{
struct MyTypeNode* node = &linkList->head;
while (node->next)
{
if (fun(&node->next->data, &data))
{
struct MyTypeNode* temp = node->next;
node->next = node->next->next;
free(temp);
break;
}
node = node->next;
}
}
//删除给定name的节点
void Remove_Name(struct MyLinkList* linkList, const char * name)
{
MyType data;
sprintf(data.name, "%s", name);
Remove(linkList, data, Equal_Value);
}
//删除给定value的节点
void Remove_Value(struct MyLinkList* linkList, int value)
{
MyType data;
data.value = value;
Remove(linkList, data, Equal_Name);
}
//利用给定fun提供的顺序,冒泡排序
void SortBubble(struct MyLinkList* linkList, MyTypeFun fun)
{
int len = LinkListCount(linkList);
for (int i = 0; i< len - 1; i++)
{//n-1轮处理
// Last i elements are already in place
int bChanged = 0;
struct MyTypeNode* node = linkList->head.next;
struct MyTypeNode* next = node->next;
for (int j = 0; j <len - i - 1; j++)
{
if (!fun(&node->data, &next->data))
{//相邻元素逆序,进行交换
MyType tmp = next->data;
next->data = node->data;
node->data = tmp;
bChanged = 1;
}
node = node->next;
next = next->next;
}
if (!bChanged)
{//没有出现位置调整的情况,也就是说,数组已经有序
return;
}
}
}
//定义name的正序,由大到小
int Func_NameGreat(const MyType* v1, const MyType* v2)
{
if ((strcmp(v1->name, v2->name) > 0) ||
(strcmp(v1->name, v2->name) == 0 && v1->value < v2->value)
)
return 1;
return 0;
}
//根据Name由大到小顺序排序
void SortBubble_NameGreate(struct MyLinkList* myList)
{
SortBubble(myList, Func_NameGreat);
}
//定义value的正序,由小到大
int Func_ValueLess(const MyType* v1, const MyType* v2)
{
if (v1->value < v2->value ||
(v1->value == v2->value && strcmp(v1->name, v2->name) < 0) )
return 1;
return 0;
}
//根据value由小到大顺序排序
void SortBubble_ValueLess(struct MyLinkList* myList)
{
SortBubble(myList, Func_ValueLess);
}
//查找给定value
MyType* Find_Value(struct MyLinkList* linkList, int data)
{
MyType v = { "", data };
return Find(linkList, v, Equal_Value);
}
//查找给定的name
MyType* Find_Name(struct MyLinkList* linkList, const char* name)
{
MyType v;
sprintf(v.name, "%s", name);
//strcpy(v.name, name);
return Find(linkList, v, Equal_Name);
}
//利用给定fun,查找包含data的节点
MyType* Find(struct MyLinkList* linkList, MyType data, MyTypeFun fun)
{
struct MyTypeNode* node = linkList->head.next;
while (node)
{
if (fun(&(node->data), &data))
{
return &(node->data);
}
node = node->next;
}
return 0;
}