线性列表——链式存储结构(带头节点)
#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; }