数据结构--链表

一、数据结构概述

1、什么是数据结构

         数据结构是计算机科学中的一种组织、管理和存储数据的方式,旨在高效地进行数据的  访        问、插入、删除和处理。不同的数据结构适用于不同的问题,提高算法的性能和效率。

2、数据结构

   1.逻辑结构
  • 线性结构:表(数据之间位一对一的关系)
  • 非线性结构:树(数据间为一对多的关系),图(数据间为多对多的关系)         
   2.存储结构

        存储结构有顺序存储(数组)、链式存储(链表)、散列存储(哈希表)、索引存储(数、图)

   3.常见数据结构 
顺序表链式表顺序栈链式栈二叉树
顺序队列链式队列邻接表邻接矩阵

二、链表

1、概念

        链表是一种常见的线性数据结构,由一系列节点组成。每个节点包含数据部分和指向下一个节点的指针(或引用)

2、链表与顺序表的特点对比

数据结构特点
顺序表

存储数据连续

访问元素方便

无法利用小空间,不需用连续的大空间

顺序表的元素是有限的

插入和删除效率低

链表

存储空间不需要连续

可以利用一些小的存储空间

访问元素不方便

链表元素可以没有上限

插入和删除效率高

3、链表分类

  • 单向链表:只能通过链表节找到后一个链表,访问链表元素的方向是单向的

  • 双向链表:能通过链表节找到前一个与后一个链表节,访问链表元素是单向的

  • 循环链表:在双向链表的基础上,能通过第一个链表节找到最后一链表节,也能通过最后一个链表节找到第一个链表节,实现链表元素的循环访问

  • 有头链表:第一个节点不存放数据,操作较简单(二级指针使用少)

  • 无头链表:第一个节点存放数据,操作较复杂(要用到较多的二级指针)

三、单向链表及其相关操作(以有头链表为例)

1、定义链表节点类型

        如下代码所示,定义链表节点类型 linknode 其中 data 存放链节的数据,*pnext 存放下一个链节的地址

typedef 数据类型 datatype;

typedef struct node{
    datatype data;
    struct node *pnext;
}linknode;

2、空链表的创建

        空链表要求:

                data不需要赋值(最好赋值),空白节点不存放数据,主要为了保证链表操作的便利性

                pnext必须赋值为NULL,表示该节点为最后一个节点

        实现代码:
linknode *create_emp_linklist(void)
{
    linknode *tmplist = NULL;

    tmplist = malloc(sizeof(linknode));    //向堆区申请空间

    if(NULL == tmplist)                    //判断是否申请成功
    {
        return NULL;
    }
   
    tmplist->pnext = NULL;                 //最后一个链表的标志

    return tmplist;
}

3、链表的插入

        头插法思路:
  • 创建新节点
  • 为新节点赋值,pnext 等于头节点中存储的下一个节点地址
  • 更新链表头节点中地址,使其指向新节点
        头插法代码实现: 
int insert_linklist(linknode *phead,datatype tmp)
{
    linknode *tmplist = NULL;
    
    tmplist = malloc(sizeof(linknode));

    if(NULL == tmplist)
    {
        printf("error");
        return -1;
    }
    
    tmplist->pnext = phead->pnext;    //插入链节下一个链接指向前一链节初始指向

    tmplist->data = tmp;              //给插入链结赋值

    phead->next = tmplist;            //前一链节指向插入链结
}
        尾插法思路:
  • 创建新节点
  • 为新节点赋值,新节点中 pnext 指向NULL,data 等于所赋初值 
  • 找到尾节点,将其 next 指向修改为新节点
        尾插法代码实现:
void insert_tail(linknode *phead,datatype tmp)
{
    linknode *ptail = NULL;
    linknode *ptmplist = NULL;

    ptmplist = malloc(sizeof(linknode));    //创建新节点
    if(ptmplist == NULL)
    {
        printf("error");
    }

    ptmplist->data = tmp;                   //为新节点赋值    
    ptmplist->pnext = NULL;  
               
    ptail = phead;                          //找到尾节点
    while(ptail->pnext != NULL)
    {
        ptail = ptail->next;
    }

    ptail->next = ptmplist;                //修改节点指向
}
      

4、链节数据显示

        思路:

                通过前一链结中存储的下一链节地址找到下一个地址中数据并打印

        代码实现:

void show_listdata(linknode *phead)
{
    linknode *tmplist = NULL;
    
    tmplist = phead;

    while(tmplist != NULL)                //判断是否到达尾链节
    {
        printf("%d ",tmplist->data);
        tmplist = tmplist->pnext;
    }
}

5、链节的删除

        思路:
  • 定义前驱节点找到需要删除的节点
  • 定义定位节点跟在前驱节点后,在释放节点空间后为前驱节点复位
        代码实现:    
//tmp:要删除的数据
int delete_linklist(linknode *phead,datatype tmp)
{
    linknode *prelist = NULL;
    linknode *loclist = NULL;
    
    prelist = phead->pnext;
    loclist = phead;

    while(prelist != NULL)
    {
        if(prelist->data == tmp)
        {
            loclist->pnext = prelist->pnext;        //定位下一个链节地址
            free(prelist);                          //删除目标节点
            prelist = loclist->pnext;               //复位先驱节点
        }
        else
        {
            prelist = prelist->pnext;
            loclist = loclist->pnext;
        }
    }
}

6、链表的销毁

        思路:
  • 定义两个指针 ploct 和 pfree,ploct用于定位,pfree 用于空间释放

  • 让两个指针都指向头节点,让 ploct 节点等于其指向的节点,释放 pfree 所在的节点空间

  • 让 pfree指向节点 等于 ploct指向借点

  • 重复前两步,ploct 指向NULL

        代码实现:
void destory_lintnode(**pphead)
{
    listnode *ploct = NULL;
    listnode *pfree = NULL;

    ploct = *pphead;
    pfree = *pphead;

    while(ploct != NULL)
    {
        ploct = ploct->pnext;       
        free(pfree);                //节点空间释放
        pfree = ploct;
    }
    
    *phead = NULL;

    return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值