链表Linklist

一、链表概念

链表也是线性表的一种,用于存取逻辑关系为线性的数据,但是和顺序表不同,链表的存储结构是链式存储,在内存中不连续,例如数据在内存中存储可能是下图:

要把链表的节点连接起来就需要通过指针来操作

所以在链表中,每个数据元素可以配有一个指针用于找到下一个元素即节点,这意味着,链表上的每个“元素”都长下图这个样子:

二、链表的特性

逻辑结构:线性结构  

存储结构:链式存储结构

特点:内存中不连续,通过指针链接

解决顺序表中的问题:长度固定和插入删除的麻烦

struct node
{
    int data;//数据域
    struct node *next;//指针域
}//

  • 单向链表

有头链表:存在一个头节点,(只作为链表开头,不存放数据)数据域无效,指针域有效。

无头链表:每一个节点的数据域和指针域都有效

1、遍历无头单向链表:

#include <stdio.h>

typedef char datatype;
typedef struct node
{
    datatype data;     //数据域,用来存放数据。
    struct node *next; //指针域,用来存放下一个节点的地址。
} link_node_t, *link_list_t;
// link_node_t A; 等同于 struct node A;
// link_list_t p; 等同于 struct node *p;

int main(int argc, char const *argv[])
{
    //1.定义4个节点
    link_node_t A = {'a', NULL};
    link_node_t B = {'b', NULL};
    link_node_t C = {'c', NULL};
    link_node_t D = {'d', NULL};

    //2.将四个节点连接起来
    A.next = &B;
    B.next = &C;
    C.next = &D;

    //3.定义一个头指针,指向第一个节点。用于遍历链表。
    link_list_t p = &A;

    //4.遍历无头链表
    while (!= NULL)    //判断p所指是否为空,不为空则说明指向链表节点。
    {
        printf("%c ", p->data); //打印节点中数据域
        p = p->next;            //让p指向下一个节点
    }
    printf("\n");
    return 0;
}

2、遍历有头单向链表:

#include <stdio.h>

typedef char datatype;
typedef struct node
{
    datatype data;     //数据域,用来存放数据。
    struct node *next; //指针域,用来存放下一个节点的地址。
} link_node_t, *link_list_t;
// link_node_t A; 等同于 struct node A;
// link_list_t p; 等同于 struct node *p;

int main(int argc, char const *argv[])
{
    //1.定义4个节点
    link_node_t A = {'a', NULL};
    link_node_t B = {'b', NULL};
    link_node_t C = {'c', NULL};
    link_node_t D = {'d', NULL};

    //2.将四个节点连接起来
    A.next = &B;
    B.next = &C;
    C.next = &D;

    //3.定义一个头节点,数据无效,指针域指向第一个节点。
    link_node_t h = {'\0', &A};

    //4.定义一个头指针,指向头节点。
    link_list_t p = &h;

    //5.遍历有头单项链表
#if 0
    //方法一:
    p = p->next; //跨过头节点,指向第一个节点。
    while (!= NULL)
    {
        printf("%c ", p->data);
        p = p->next;
    }
    printf("\n");
#else
    //方法二:
    while (p->next != NULL)
    {
        p = p->next;
        printf("%c ", p->data);
    }
    printf("\n");
#endif
    return 0;
}

链表尾插法练习:

写一个有头单项链表,用于保存输入的学生成绩,实现一输入学生成绩就创建一个新的节点,将成绩保存起来。再将该节点链接到链表的尾,直到输入-1结束。

要求:每个链表的节点由动态内存分配得到 , 也就是用malloc。

过程:

  1. malloc申请空间link_node_t大小作为头节点
  2. 将新节点放到链表尾部

先实现输入学生成绩,直到-1结束:

#include <stdio.h>
typedef struct node_t
{
    int score;
    struct node_t *next;
}link_node_t,* link_list_t;

int main(int argc, char const *argv[])
{
    int score = -1;
    while (1)
    {
        scanf("%d", &score);
        if (score == -1)
            break;
        
    }
    //1.malloc申请空间,创建一个新节点用于保存学生成绩。
    //2.将新节点链接到连表的尾部
    return 0;
}

继续实现malloc申请新节点存入学生成绩然后连接到链表尾部:

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
    int score;
    struct node_t *next;
}link_node_t,*link_list_t;
int main(int argc, char const *argv[])
{
    int score ;
    link_list_t pnew=NULL;//新节点地址指针
    link_list_t ptail=NULL;//链表尾巴地址指针
    //1.malloc申请空间,创建一个新节点用于保存学生成绩。
    link_list_t h=(link_list_t)malloc(sizeof(link_node_t)); //创建一个头节点,用头指针h指向头节点
    if(NULL==h)//判断成功开辟空间
    {
        perror("h malloc err");
        return -1;
    }
    h->score='\0';//头节点初始化
    h->next=NULL;
    ptail=h;//指向头节点
    //2、循环输入学生成绩,直到-1结束。并且新输入一个成绩创建一个新节点存入,然后把新节点链接到链表尾巴
    while (1)
    {
        scanf("%d",&score);
        getchar();
        if(score==-1)
        { 
           break;
        }
        else
        {
            pnew=(link_list_t)malloc(sizeof(link_node_t));//(1)创建一个新的节点用来保存输入学生成绩
            pnew->next=NULL;//新节点指针域赋空值
            pnew->score=score;//(2)对新节点的数据域和指针域进行赋值
            ptail->next=pnew;//(3)将新节点连接到链表尾部
            ptail=pnew;  //(4)链表延长一个新节点,需要将尾指针移动到新的节点作为尾巴
        }
    }
    //3.遍历有头链表
    while (h->next!=NULL)//判断p是否指向为空,若不为空则说明指向了下一个节点
    {
        h=h->next;//将下一个节点地址赋值给p
        printf("%d ",h->score);
    }
    puts(" ");
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

满山的猴子我的腚最红

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值