编译器:VS2022
构建形式:创建项目管理代码
头文件:chainList.h,主要用于存放各种结构体以及函数声明
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<assert.h>
#include<string.h>
typedef struct Book
{
char ISBN[14];
char name[20];
float price;
}Book;
typedef struct Node
{
Book book;
struct Node* next;
}Node;
Node* creatHeadNode(void);
Node* creatNewNode(Book book);
void insertBook_end(Node* headNode,Book book);
void insertBook_front(Node* headNode, Book book);
void insertBook_middle(Node* headNode, Book book, Book posBook);
void deleteBook_end(Node* headNode);
void deleteBook_front(Node* headNode);
void deleteBook_middle(Node* headNode, Book posBook);
void traverseList(Node* headNode);
void destroyList(Node* headNode);
int countList(Node* headNode);
Node* searchBook_price(Node* headNode);
源文件:chainList.c和test.c,其中chainList.c用于函数的实现,test.c用于函数的运行
chainList.c内容如下:
#include "chainList.h"
//创建一个表头
Node* creatHeadNode(void)
{
Node*headNode= (Node*)malloc(sizeof(Node));
assert(headNode);
//注:对于表头的数据域不做处理
headNode->next = NULL;
return headNode;
}
//创建节点(和创建表头的区别在于对于数据域的处理)
Node* creatNewNode(Book book)
{
Node* newNode = (Node*)malloc(sizeof(Node));
assert(newNode);
newNode->book = book;
newNode->next = NULL;
}
//链表的遍历
void traverseList(Node* headNode)
{
//因为有头链表的表头没有存储数据,所以选择从表头的下一个节点开始遍历
Node* temp = headNode->next;
while (temp!=NULL)
{
printf("%s %s %.2f\n", temp->book.ISBN, temp->book.name,temp->book.price);
temp = temp->next;
}
}
//数据尾插
void insertBook_end(Node* headNode,Book book)
{
Node* temp = headNode;
//找到尾部(尾部节点的特点是什么?tailNode->next=NULL(而不是tailNode=NULL,修改的时候也是如此))
while (temp->next != NULL)
{
temp = temp->next;
}
//创建一个新的节点
Node*newNode = creatNewNode(book);
//与原来的链表相连接
temp ->next = newNode;
}
//数据头插
void insertBook_front(Node* headNode, Book book)
{
//先保存原来的第一个节点
Node* temp = headNode->next;
//创建新的节点插入到头指针的后面
headNode->next = creatNewNode(book);
//将原来的第一个节点接到插入的节点的后面
headNode = headNode->next;
headNode->next = temp;
}
//在指定数据的位置前插(posBook是目标书的位置)
void insertBook_middle(Node* headNode, Book book, Book posBook)
{
//首先第一步是找到posBook所在的节点位置,然后记录其前驱
//所以需要两个指针,并排走(因为链表是有方向的)
//创建好这个新的节点
Node* newNode = creatNewNode(book);
//目标位置
Node* posNode = headNode->next;
//目标位置的前驱
Node* preNode = headNode;
//注意结构体的比较不能直接算数比较(><)[注意,这里存在短路现象,自己看看结尾]
//寻找指定的节点的写法非常固定的,需要记住
while (posNode->next!= NULL && strcmp(posNode->book.ISBN,posBook.ISBN)!=0)
{
//并排向后走
posNode = posNode->next;
preNode = preNode->next;
}
//短路现象补充判断
if (strcmp(posNode->book.ISBN, posBook.ISBN) != 0)
{
printf("没有发现该书,请重新确认\n");
}
//找到了该节点,连接
else
{
preNode ->next= newNode;
newNode->next=posNode;
}
}
//数据尾删(注意不能传入空的链表(只有表头))
void deleteBook_end(Node*headNode)
{
//依旧是前驱加后继双节点
Node* posNode = headNode->next;
Node* preNode = headNode;
//尾节点的特点是其指针域的值为NULL
while (posNode->next!= NULL)
{
posNode = posNode->next;
preNode = preNode->next;
}
free(posNode);
preNode->next = NULL;
}
//数据头删(注意不能传入空的链表(只有表头))
void deleteBook_front(Node* headNode)
{
//依旧是前驱加后继双节点
Node* posNode = headNode->next;
Node* preNode = headNode;
//将头指针和第二个相连
preNode->next = posNode->next;
//释放第一个节点
free(posNode);
}
//指定位置删除:将指定位置节点删除
void deleteBook_middle(Node* headNode,Book posBook)
{
//目标位置
Node* posNode = headNode->next;
//目标位置的前驱
Node* preNode = headNode;
//注意结构体的比较不能直接算数比较(><)[注意,这里存在短路现象,自己看看结尾]
//寻找指定的节点的写法非常固定的,需要记住
while (posNode->next != NULL && strcmp(posNode->book.ISBN, posBook.ISBN) != 0)
{
//并排向后走
posNode = posNode->next;
preNode = preNode->next;
}
//短路现象补充判断
if (strcmp(posNode->book.ISBN, posBook.ISBN) != 0)
{
printf("没有发现该书,请重新确认\n");
}
//找到了该节点,删除
else
{
preNode->next = posNode->next;
free(posNode);
}
}
//链表的销毁
void destroyList(Node* headNode)
{
//从表头的下一个,也就是第一个节点开始删除
Node* posNode = headNode->next;
//当第一个节点的指针域不为空(最终删到只有头结点和第一个节点)的时候,持续删除
while (posNode->next!= NULL)
{
deleteBook_end(headNode);
}
//最后释放表头和第一个节点
free(posNode);
free(headNode);
}
//节点个数的统计
int countList(Node* headNode)
{
int count = 0;
Node* posNode = headNode->next;
while (posNode != NULL)
{
posNode = posNode->next;
count++;
}
return count;
}
//数据的查找(查找最高价格),返回价格最高的书的节点(只能查找其中的一个,查询所有的将在后续完善)
Node* searchBook_price(Node* headNode)
{
Node* posNode = headNode->next;
Node* temp = posNode;
//一直向后,直到最后一个节点停止,最终posNode是最后一个节点
while (posNode->next != NULL)
{
//如果有节点的价格大于temp节点中的价格,则更新数据
if (posNode->book.price > temp->book.price)
{
temp = posNode;
}
posNode = posNode->next;
}
return temp;
}
test.c用于函数测试,可以根据需要进行更改,测试,由于在编写的过程中我已验证过其余函数的正确性,代码中只验证了searchBook_price函数。希望读者在代码移植后对其中的函数进行一一测试,防止编译器不同所带来的差异。
#include"chainList.h"
int main()
{
Node* headNode = creatHeadNode();
Book book0 = { "0000","NNN",12.5 };
Book book1 = { "1111","mmm",22.5 };
Book book2 = { "2222","ppp",32.5 };
Book book3 = { "3333","qqq",42.5 };
Book book4 = { "4444","ccc",52.5 };
insertBook_end(headNode, book0);
insertBook_end(headNode, book1);
insertBook_end(headNode, book2);
insertBook_end(headNode, book3);
traverseList(headNode);
printf("------------------------\n");
Node*p = searchBook_price(headNode);
printf("%f", p->book.price);
return 0;
}
对于pdf中的实验要求,只写了一部分,还有待完善,将在后续更新...