【C】【List】简易链表实现

简易链表实现

//链表储存电影列表
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 20
#include <stdio.h>
#include <stdlib.h>//malloc()
#include <stdbool.h>
#include <string.h>//strchr()在字符串中查询字符

//创建一个具体的项目,含有各种属性,并抽象化
typedef struct movie {
	char movie_name[SIZE];
	double score;
}Item;

//创建一个节点,含有项目和指向前后节点的节点指针
typedef struct node {
	Item item;
	struct node* previous;
	struct node* next;
}Node;

//创建一个链表,含有头尾节点及指向当前节点的node节点指针
typedef struct {
	Node* head;
	Node* node;
	Node* end;
	int node_num;
}List;

//初始化链表
bool InitList(List* plist);
bool InitList(List* plist) 
{
	//分配内存空间
	//尝试过初始化为NULL,会报错指针为NULL无法赋值
	plist->head = (Node*)malloc(sizeof(Node));
	plist->node = (Node*)malloc(sizeof(Node));
	plist->end = (Node*)malloc(sizeof(Node));
	plist->node_num = 0;
	plist->end = NULL;

	//头节点的next指向尾结点,中间无节点,即链表为空
	plist->head->next = plist->end;
	if (plist->head->next == plist->end)
		return true;

	return false;
}

//判断链表是否为空
bool ListIsEmpty(List* plist);
bool ListIsEmpty(List* plist) 
{
	//头节点的next指向尾结点,中间无节点,即链表为空
	if (plist->head->next == plist->end)
		return true;
	return false;
}

//判断链表是否已满
bool ListIsFull(List* plist);
bool ListIsFull(List* plist) 
{
	//创建一个新节点并分配内存空间
	Node* ptemp;
	ptemp = (Node*)malloc(sizeof(Node));

	//当内存不足无法创建新节点时,说明链表已满
	if (ptemp == NULL)
	{
		free(ptemp);//释放内存
		return true;
	}

	free(ptemp);//释放内存
	return false;
}

//增加一个新的节点
bool AddNode(List* plist, Item item);
bool AddNode(List* plist, Item item) 
{
	//创建一个新节点并分配内存空间
	Node* pnew;
	pnew = (Node*)malloc(sizeof(Node));
	//不进行判断,会使程序取消对指针的引用
	if (pnew == NULL)
		return false;

	plist->node_num++;//节点数量增加
	pnew->item = item;//项目导入新节点
	pnew->next = plist->end;//新节点next指向尾结点

	//如何链表为空,对头节点操作
	//一定要先对头节点操作
	if (ListIsEmpty(plist) == true)
		plist->head->next = pnew;

	//如果链表非空,对当前节点操作
	else if (ListIsEmpty(plist) == false)
		plist->node->next = pnew;
	
	plist->node = pnew;//记入当前节点位置
    
	return true;
}

//释放链表内存
void FreeList(List* plist);
void FreeList(List* plist)
{
	Node* psave;

	while (ListIsEmpty(plist) != true)
	{
		psave = plist->head->next;//保存下一个节点
		free(plist->head);//释放当前节点
		plist->head = psave;//头节点向前推进
	}
}

//用户自定义输入
bool scanf_user(Item* item);
bool scanf_user(Item* item) {
	char* find;
	bool flag = true;

	printf("请输入电影名:\n");
	//一般用fgets读取字符串
	//fgets会在输入流最后自动添加停止符
	//当从stdin流输入时,最后的换行符会被读入,一般用以下方式使用
	if (fgets(item->movie_name, SIZE, stdin) != NULL)
	{
		//查找字符串中换行符转换为停止符
		find = strchr(item->movie_name, '\n');
		if (find)
			*find = '\0'; 
		else
			//处理输入行剩余内容
			while (getchar() != '\n')
				continue;
	}

	//如果字符串为空就停止输入
	if (item->movie_name[0] == '\0')
		flag = false;

	if (flag == true)
	{
		printf("请输入评分:\n");
		if (scanf("%lf", &item->score) == false)
			return false;

		//处理输入行剩余内容
		while (getchar() != '\n')
			continue;
		return true;
	}
	else
		return false;
}

//用户自定义输出
void printf_user(Node* scan);
void printf_user(Node* scan)
{
	
		//判断是不是浮点数
		if ((int)scan->item.score == scan->item.score)
			printf("%s\t\t%d\n", scan->item.movie_name, (int)scan->item.score);
		else
			printf("%s\t\t%.1lf\n", scan->item.movie_name, scan->item.score);
}

//遍历链表打印内容
bool ScanList(List* plist);
bool ScanList(List* plist)
{
	Node* scan;
	scan = (Node*)malloc(sizeof(Node));

	printf("共%d部电影\n", plist->node_num);
	printf("电影\t\t评分\n");
	
	//遍历链表
	scan = plist->head->next;
	while (scan != NULL)
	{
		printf_user(scan);
		scan = scan->next;
	}

	return true;
}

int main()
{
	List movie;
	Item item;

	if (InitList(&movie))
		printf("程序运行……\n");
	else
	{
		printf("程序错误!\n");
		exit(1);
	}

	system("pause");
	system("cls");

	while ((scanf_user(&item) == true))
	{
		if (AddNode(&movie, item) == false)
			break;
	}
	system("cls");

	if (ListIsEmpty(&movie) == true)
		printf("链表为空!\n");
	else
		ScanList(&movie);

	FreeList(&movie);
}

--------------------2022年3月23日--------------------
FreeList()修改

void FreeList(List* plist);
void FreeList(List* plist)
{
	Node* psave;

	while (ListIsEmpty(plist) != true)
	{
		psave = plist->head;//保存当前头节点
		plist->head = plist->head->next;//头节点向前
		free(psave);//释放节点
	}
}

原来的方法其实不会向前推进头节点

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值