(tips:上面的代码中将头节点中的数据当作第一个元素,大多数情况头节点是不存储数据的(当时没注意···),读者可自行尝试修改代码让头结点不存储数据,头节点的后一个节点作为第一个元素)
下面附上头结点不存储数据的代码(区别不是很大,就是多用了一个子函数来初始化头结点)
#include <stdio.h>
#include <stdlib.h>
struct link *AppendNode (struct link *head);
void DisplyNode (struct link *head);
void DeletMemory (struct link *head);
struct link *init (struct link *head);
struct link
{
int data;
struct link *next;
};
int main(void)
{
int i = 0;
char c;
struct link *head = NULL; //链表头指针
head = init(head); /* 初始化队列 */
printf("Do you want to append a new node(Y/N)?");
scanf_s(" %c", &c); //%c前有一个空格
while (c == 'Y' || c == 'y')
{
head = AppendNode(head);//向head为头指针的链表末尾添加节点
DisplyNode(head); //显示当前链表中的各节点的信息
printf("Do your want to append a new node(Y/N)");
scanf_s(" %c", &c); //%c前有一个空格
i++;
}
printf("%d new nodes have been apended", i);
DeletMemory(head); //释放所有动态分配的内存
return 0;
}
//函数功能:初始化链表,即新建一个头结点(此处头结点不放数据,原则上不放,实际还是可以放数据)
struct link *init (struct link *head)
{
struct link *p = NULL;
p = (struct link *)malloc(sizeof(struct link));
if (p == NULL)
{
printf("初始化链表失败\n");
exit(0);
}
head = p;
p->next = NULL;
return head;
}
//函数功能:新建一个节点并添加到链表末尾,返回添加节点后的链表的头指针
struct link *AppendNode(struct link *head)
{
struct link *p = NULL, *pr = head;
int data;
p = (struct link *)malloc(sizeof(struct link));//让p指向新建的节点
if (p == NULL) //若新建节点申请内存失败,则退出程序
{
printf("No enough memory to allocate\n");
exit(0);
}
if (head->next == NULL) //若原链表为空表(只有头节点,头节点不存储数据为空表)
{
printf("Input node data");
scanf_s("%d", &data);
head->next = p; /* 让头结点的指针指向新建节点 */
p->data = data;
p->next = NULL; /* 新建结点置为表尾 */
return head;
}
else //若原链表为非空,则将新建节点添加到表尾
{
while (pr->next != NULL)//若未到表尾,则移动pr直到pr指向表尾
{
pr = pr->next; //让pr指向下一个节点
}
pr->next = p; //让末节点的指针指向新建的节点
printf("Input node data");
scanf_s("%d", &data); //输入节点数据
p->data = data; //将新建节点的数据域赋值为输入的节点数据值
p->next = NULL;//将新建的节点置为表尾
return head; //返回添加节点后的链表的头指针
}
}
//函数的功能:显示链表中所有节点的节点号和该节点中的数据项的内容
void DisplyNode (struct link *head)
{
struct link *p = head;
int j = 1;