链表代码解读

一、链表的概念

定义:

      链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。

特点:

      链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时动态生成 (malloc),每个节点包括两个部分:

     一个是存储数据元素的数据域

     另一个是存储下一个节点地址的指针域

图1 单向链表

 链表的构成:

      链表由一个个节点构成,每个节点一般采用结构体的形式组织,例如:

 
  1. typedef struct student{

  2. int num;

  3. char name[20];

  4. struct student *next;

  5. }STU;

      链表节点分为两个域

      数据域:存放各种实际的数据,如:num、score等

      指针域:存放下一节点的首地址,如:next等.

图2 节点内嵌在一个数据结构中

链表的操作:

      链表最大的作用是通过节点把离散的数据链接在一起,组成一个表,这大概就是链表 的字面解释了吧。 链表常规的操作就是节点的插入和删除,为了顺利的插入,通常一条链 表我们会人为地规定一个根节点,这个根节点称为生产者。通常根节点还会有一个节点计 数器,用于统计整条链表的节点个数,具体见图3中的 root_node。

图3带根节点的链表

 双向链表

      双向链表与单向链表的区别就是节点中有两个节点指针,分别指向前后两个节点,其 它完全一样。有关双向链表的文字描述参考单向链表小节即可,有关双向链表的示意图具体见图4

#include <stdio.h>
#include <stdlib.h>
//定义结点结构体
typedef struct student{
    //数据域
    int num;//学号
    int score;//分数
    char name[20];//姓名
    //指针域
    struct studen *next;
}STU;

void link_creat_head(STU **p_head,STU *p_new)
{
    STU *p_mov=*p_head;
    if(*p_head==NULL)//当第一次加入链表为空时,head执行p_new
    {
        *p_head=p_new;
        p_new->next!NULL;
    }
    else//第二次以后加入链表
    {
        while(p_mov->next!=NULL)
        {
            p_mov=p_mov->next;//将新申请的节点加入链表
            p_new->next=NULL;
        }
    }
}
int main()
{
    STU *head=NULL,*p_new=NULL;
    int num,i;
    printf("请输入初始链表个数:\n");
    scanf("%d",num);\
    for(i=0;i<num;i++)
    {
        p_new=(STU*)malloc(sizeof(STU));//申请一个新节点
        printf("请输入学号、分数、名字:\n");//给新节点赋值
        scanf("%d %d %s",&p_new->num,&p_new->score,p_new->name);

        link_creat_head(&head,p_new);//将新节点加入链表
    }
}

 typedef的理解

typedef是类型定义的意思。typedef struct 是为了使用这个结构体方便。
具体区别在于:
若struct node {}这样来定义结构体的话。在申请node 的变量时,需要这样写,struct node n;
若用typedef,可以这样写,typedef struct node{}NODE; 。在申请变量时就可以这样写,NODE n;
区别就在于使用时,是否可以省去struct这个关键字。

malloc函数的理解

当我们需要做一个成绩管理系统,人数可能为全校学生,也可能为一个班的学生,当我们开辟一个班的数组大小时,如果要存储整个学校的人数时,会出现内存不够用的情况;当我们开辟全校人数大小的数组时,输入一个班人数的大小时,会出现内存浪费的情况。
为了应对上述问题,我们引入malloc函数。

malloc函数使用形式

关于malloc所开辟空间类型:malloc只开辟空间,不进行类型检查,只是在使用的时候进行类型的强转。
举个例子:‘我’开辟你所需要大小的字节大小空间,至于怎么使用是你的事
mallo函数返回的实际是一个无类型指针,必须在其前面加上指针类型强制转换才可以使用
指针自身 = (指针类型*)malloc(sizeof(指针类型)*数据数量)

scanf 输入

如果p_new是一个指向STU类型的结构体变量的指针,那么你可以通过(*p_new).num或者p_new->num来访问num成员变量。

如果p_new是一个STU类型的结构体变量而不是指针,那么你可以直接使用p_new.num来访问num成员变量。

所以,p_new->num的写法是因为p_new是一个指向结构体的指针,而不是结构体本身

 链表函数的理解

void link_creat_head(STU **p_head,STU *p_new)
{
    STU *p_mov=*p_head;
    if(*p_head==NULL)//当第一次加入链表为空时,head执行p_new
    {
        *p_head=p_new;
        p_new->next!NULL;
    }
    else//第二次以后加入链表
    {
        while(p_mov->next!=NULL)
        {
            p_mov=p_mov->next;//将新申请的节点加入链表
            p_new->next=NULL;
        }
    }
}

1.*p_head表示指向的是p_head所指向的地址中存储的内容。在这种情况下,p_head应该是一个指向指针的指针,因此*p_head将会得到p_head指向的地址中存储的内容,也就是指向的是链表的头部节点的地址。STU *p_mov 得到的是 *p_head 指向的地址中存储的内容,也就是链表头部节点的地址。实际上,STU *p_mov 是一个指向链表中的节点的指针,而不是指向链表头部节点的指针。

2.*p_head = p_new;:这行代码将指向链表头部的指针 p_head 指向了一个新的节点 p_new。这样就实现了在链表头部插入新节点的操作。p_new 是一个指向新节点的指针。在这个上下文中,p_new 是一个指向 STU 类型的节点的指针。通常情况下,我们会使用 malloc 或者类似的方法来分配内存给 p_new,然后设置它的值,最后将它插入到链表中。

3.p_new->next = NULL;:这行代码将新节点 p_new 的 next 指针指向了 NULL,表示新节点成为了链表的头部,而且是链表中的第一个节点,因此它的 next 指针应该指向 NULL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值