线性列表——链式存储结构(带头节点)

#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;
}
原文地址:https://www.cnblogs.com/gti2baby/p/11666717.html