#include<stdio.h>
//线性列表——链式存储结构(带头节点)
/* 第一个node无前趋,所以设置一个head指针指向第一个节点
最后一个节点没有直接后继,最后一个节点的指针设为“NULL”
node{data,next}
*/
typedef int DataType;
/*自定义数据类型,
先定义成int,可修改成其他类型*/
typedef struct node{
DataType data;//数据区
struct node *next;//指针域
//指向 struct node类型的指针
}Node;
//struct node定义了一个数据类型、Node是该类型别名
/*
头节点:其实就是一个不存任何数据的空节点,
通常作为链表的第一个节点。对于链表来说,
头节点不是必须的,它的作用只是为了方便解决某些实际问题;
首元节点:由于头节点(也就是空节点)的缘故,
链表中称第一个存有数据的节点为首元节点。
首元节点只是对链表中第一个存有数据节点的一个称谓,
没有实际意义;
*/
Node *Creatlist()
//返回指针的函数,没有什么特别的,只是返回值是指针
{
/*建立带头节点的链表,返回头节点指针*/
Node *head=NULL;//head是头指针
Node *s=NULL,*tail=NULL;//s是节点指针,tail是尾指针
DataType x=0;
head = (Node *)malloc(sizeof(Node));//建立头节点,由head指向
/*此处的 (Node *)malloc(sizeof(Node))
分成三部分来看;
(Node *),声明这是Node类型的指针
malloc是c库函数,作用是返回一个指针,指向已经申请的一块内存区域
sizeof(Node),计算内存区的大小
*/
tail=head;//首尾同指向第一个节点
scanf("%d",&x);//为第二节点数据装填做准备
/*
小技巧,为的是使得下面的循环可用
注意:在此处我将头节点描述为第一节点
*/
while(x!=0)
{
s =(Node *)malloc(sizeof(Node));
s->data = x;//第二节点数据装填
tail->next = s;//挂钩,形成链条
tail = s;
/*最开始tail指向第一节点
然后,s指向第二节点内存区,
tail->next = s;这句,将第二节点地址赋给了第一节点的指针区
称为挂钩
*/
scanf("%d",&x);//为下一节点数据区装填做准备
}
s->tail = NULL;
return head;
}
int Findlist(Node *head,DataType x)
{//查找列表元素,并返回值
/* 1、判空
2、查找
3、返回
*/
Node *p;
p=head->next;
while(p!=NULL&&p->data!=x)
{
p=p->next;
}
if (p!=NULL) return p;
else return NULL;
}
int Lengthlist(Node *head)
{//求链表长度 ,包含元节点
/* 初始化计数器;
结点不空,重复下列操作:
计数器增1
结点后移1
*/
Node *p;
p = head->next;//?
int len=0;
while(p!=NULL)
{
len++;
p = p->next;
}
return len;
}
int
int main()
{
Node *head = Creatlist();//创建单向链表
Findlist(head,x);//查找元素
Lengthlist(head)//求链表长度
return 0;
}