双向链表、单双向链表比较、双向链表的基本操作

news2024/12/24 20:24:56

我要成为嵌入式高手之3月20日数据结构第三天!!
————————————————————————————

双向链表

        双向链表与单向链表的区别:双向链表中的结点的指针域包含前驱结点的地址,而单向链表的结点中指针域只有后驱结点的地址。

        双向链表操作前驱结点比单向链表方便:单向链表若是要操作前驱结点就始终要用一个指针指向前驱结点,否则很容易丢失前驱结点地址,就要重新进行遍历。

1、创建链表

TWO_LIST *CreateLink()
{
    TWO_LIST *plist = malloc(sizeof(TWO_LIST));
    if (NULL == plist)
    {
        perror("fail to malloc list");
        return NULL;
    }

    plist->phead = NULL;
    plist->clen = 0;
    
    return plist;
}

2、创建结点

TWO_NODE *CreateNode(DATA_STU data)
{
    TWO_NODE *pnode = malloc(sizeof(TWO_NODE));
    if (NULL == pnode)
    {
        perror("fail to malloc node");
        return NULL;
    }
    
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    return pnode;
}

3、头插

int PushHeadNode(TWO_LIST *plist, TWO_NODE *pnode)
{
    if (pnode == NULL || plist == NULL)
    {
        return -1;
    }

    if (plist->phead == NULL)
    {
        plist->phead = pnode;
    }
    else
    {
        pnode->pnext = plist->phead;
        plist->phead->ppre = pnode;
        plist->phead = pnode;
    }

    plist->clen++;

    return 0;
}

4、尾插

int PushTailNode(TWO_LIST *plist, TWO_NODE *pnode)
{
    TWO_NODE *ptmp = NULL;

    if (pnode == NULL || plist == NULL)
    {
        return -1;
    }

    if (plist->phead == NULL)
    {
        plist->phead = pnode;
    }
    else
    {
        ptmp = plist->phead;
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        ptmp->pnext = pnode;
        pnode->ppre = ptmp;
    }

    plist->clen++;

    return 0;
}

5、从头遍历

int SearchHeadAll(TWO_LIST *plist)
{
    TWO_NODE *ptmp = plist->phead;

    if (plist->phead == NULL)
    {
        printf("NO NODE!\n");
        return -1;
    }
    else
    {
        while (ptmp != NULL)
        {
            printf("StuInfo:\nid = %d; name = %s; score = %d.\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
            ptmp = ptmp->pnext;
        }
    }

    printf("len = %d\n", plist->clen);
    return 0;
}

6、从尾遍历

int SearchTailAll(TWO_LIST *plist)
{
    TWO_NODE *ptmp = plist->phead;

    if (plist->phead == NULL)
    {
        printf("NO NODE!\n");
        return -1;
    }
    else
    {
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        while (ptmp != NULL)
        {
            printf("StuInfo:\nid = %d; name = %s; score = %d.\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
            ptmp = ptmp->ppre;
        }
    }
    printf("len = %d\n", plist->clen);
    return 0;
}

7、查找

TWO_NODE *SearchInLink(TWO_LIST *plist, int id)
{
    TWO_NODE *dest = plist->phead;

    while (dest != NULL)
    {
        if (dest->data.id != id)
        {
            dest = dest->pnext;
        }
        else
        {
            return dest;
        }
    }
    return NULL;
}

8、修改

int ChangeInLink(TWO_LIST *plist, int uid, DATA_STU sdata)
{
    TWO_NODE *ptmp = plist->phead;

    while (ptmp != NULL)
    {
        if (ptmp->data.id != uid)
        {
            ptmp = ptmp->pnext;
        }
        else
        {
            ptmp->data = sdata;
            return 1;
        }
    }
    return -1;
}

9、头删

int PopHeadLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = plist->phead;

    if (NULL == plist->phead)
    {
        return -1;
    }
    else
    {
        pfree->pnext->ppre = NULL;
        plist->phead = pfree->pnext;
        free(pfree);
        plist->clen--;
    }

    return 0;
}

10、尾删

int PopTailLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = plist->phead;
    if (NULL == plist->phead)
    {
        return -1;
    }
    else if (NULL == plist->phead->pnext)
    {
        free(pfree);
    }
    else
    {
        while (pfree->pnext != NULL)
        {
            pfree = pfree->pnext;
        }
        pfree->ppre->pnext = NULL;
        free(pfree);
    }
    plist->clen--;

    return 0;
}

11、销毁

int DestroyLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = NULL;
    TWO_NODE *ptmp = plist->phead;

    if (NULL == plist->phead)
    {
        free(plist);
    }
    else
    {
        while (NULL != ptmp)
        {
            pfree = ptmp;
            ptmp = ptmp->pnext;
            plist->phead = ptmp;
            free(pfree);
        }
        free(plist);
    }

    return 0;
}

 完整代码:

头文件:

#ifndef _LINK_H_
#define _LINK_H_

#include <stdio.h>
#include <stdlib.h>

/* 存储的数据类型 */
typedef struct stu
{
    int id;
    char name[32];
    int score;
}DATA_STU;

/* 链表的结点类型 */
typedef struct node
{
    DATA_STU data;        //数据域
    struct node *pnext;    //后驱结点
    struct node *ppre;     //前驱结点
}TWO_NODE;

/* 描述链表属性的标签类型 */
typedef struct list
{
    TWO_NODE *phead;      //存储头结点地址的指针
    int clen;              //链表中当前结点个数
}TWO_LIST;

extern TWO_LIST *CreateLink();
extern TWO_NODE *CreateNode(DATA_STU data);
extern int PushHeadNode(TWO_LIST *plist, TWO_NODE *pnode);
extern int SearchHeadAll(TWO_LIST *plist);
extern int SearchTailAll(TWO_LIST *plist);
extern int PushTailNode(TWO_LIST *plist, TWO_NODE *pnode);
extern TWO_NODE *SearchInLink(TWO_LIST *plist, int id);
extern int ChangeInLink(TWO_LIST *plist, int uid, DATA_STU sdata);
extern int PopHeadLink(TWO_LIST *plist);
extern int PopTailLink(TWO_LIST *plist);
extern int DestroyLink(TWO_LIST *plist);

#endif

功能函数文件:

#include "head.h"

TWO_LIST *CreateLink()
{
    TWO_LIST *plist = malloc(sizeof(TWO_LIST));
    if (NULL == plist)
    {
        perror("fail to malloc list");
        return NULL;
    }

    plist->phead = NULL;
    plist->clen = 0;
    
    return plist;
}

TWO_NODE *CreateNode(DATA_STU data)
{
    TWO_NODE *pnode = malloc(sizeof(TWO_NODE));
    if (NULL == pnode)
    {
        perror("fail to malloc node");
        return NULL;
    }
    
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    return pnode;
}

int PushHeadNode(TWO_LIST *plist, TWO_NODE *pnode)
{
    if (pnode == NULL || plist == NULL)
    {
        return -1;
    }

    if (plist->phead == NULL)
    {
        plist->phead = pnode;
    }
    else
    {
        pnode->pnext = plist->phead;
        plist->phead->ppre = pnode;
        plist->phead = pnode;
    }

    plist->clen++;

    return 0;
}

int SearchHeadAll(TWO_LIST *plist)
{
    TWO_NODE *ptmp = plist->phead;

    if (plist->phead == NULL)
    {
        printf("NO NODE!\n");
        return -1;
    }
    else
    {
        while (ptmp != NULL)
        {
            printf("StuInfo:\nid = %d; name = %s; score = %d.\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
            ptmp = ptmp->pnext;
        }
    }

    printf("len = %d\n", plist->clen);
    return 0;
}

int SearchTailAll(TWO_LIST *plist)
{
    TWO_NODE *ptmp = plist->phead;

    if (plist->phead == NULL)
    {
        printf("NO NODE!\n");
        return -1;
    }
    else
    {
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        while (ptmp != NULL)
        {
            printf("StuInfo:\nid = %d; name = %s; score = %d.\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
            ptmp = ptmp->ppre;
        }
    }
    printf("len = %d\n", plist->clen);
    return 0;
}

int PushTailNode(TWO_LIST *plist, TWO_NODE *pnode)
{
    TWO_NODE *ptmp = NULL;

    if (pnode == NULL || plist == NULL)
    {
        return -1;
    }

    if (plist->phead == NULL)
    {
        plist->phead = pnode;
    }
    else
    {
        ptmp = plist->phead;
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        ptmp->pnext = pnode;
        pnode->ppre = ptmp;
    }

    plist->clen++;

    return 0;
}

TWO_NODE *SearchInLink(TWO_LIST *plist, int id)
{
    TWO_NODE *dest = plist->phead;

    while (dest != NULL)
    {
        if (dest->data.id != id)
        {
            dest = dest->pnext;
        }
        else
        {
            return dest;
        }
    }
    return NULL;
}

int ChangeInLink(TWO_LIST *plist, int uid, DATA_STU sdata)
{
    TWO_NODE *ptmp = plist->phead;

    while (ptmp != NULL)
    {
        if (ptmp->data.id != uid)
        {
            ptmp = ptmp->pnext;
        }
        else
        {
            ptmp->data = sdata;
            return 1;
        }
    }
    return -1;
}

int PopHeadLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = plist->phead;

    if (NULL == plist->phead)
    {
        return -1;
    }
    else
    {
        pfree->pnext->ppre = NULL;
        plist->phead = pfree->pnext;
        free(pfree);
        plist->clen--;
    }

    return 0;
}

int PopTailLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = plist->phead;
    if (NULL == plist->phead)
    {
        return -1;
    }
    else if (NULL == plist->phead->pnext)
    {
        free(pfree);
    }
    else
    {
        while (pfree->pnext != NULL)
        {
            pfree = pfree->pnext;
        }
        pfree->ppre->pnext = NULL;
        free(pfree);
    }
    plist->clen--;

    return 0;
}

int DestroyLink(TWO_LIST *plist)
{
    TWO_NODE *pfree = NULL;
    TWO_NODE *ptmp = plist->phead;

    if (NULL == plist->phead)
    {
        free(plist);
    }
    else
    {
        while (NULL != ptmp)
        {
            pfree = ptmp;
            ptmp = ptmp->pnext;
            plist->phead = ptmp;
            free(pfree);
        }
        free(plist);
    }

    return 0;
}

主函数文件

#include "head.h"

int main(void)
{
    TWO_LIST *plist = NULL;
    TWO_NODE *pnode = NULL;
    int i = 0;
    int uid = 0;

    /* 创建双向链表 */
    plist = CreateLink();
    if (NULL == plist)
    {
        perror("fail to CreateLink");
        return -1;
    }
    
    /* 初始化要插入结点的数据 */
    DATA_STU data[5] = {
        {1, "zhangsan", 99},
        {2, "lisi", 98},
        {3, "wangwu", 97},
        {4, "aaaaa", 96},
        {5, "bbbbb", 95},
    };

    DATA_STU data1[5] = {
        {6, "zhangsan", 99},
        {7, "lisi", 98},
        {8, "wangwu", 97},
        {9, "aaaaa", 96},
        {10, "bbbbb", 95},
    };
    
    /* 创建头插结点并头插 */
    for (i = 0; i < 5; ++i)
    {
        pnode = CreateNode(data[i]);
        if (NULL == pnode)
        {
            perror("fail to CreateNode");
            return -1;
        }
        PushHeadNode(plist, pnode);
    }
#if 0
    /* 从头遍历、从尾遍历*/
    SearchHeadAll(plist);
    printf("==============================\n");
    SearchTailAll(plist);
    printf("TAIL==========================\n");
#endif
    /* 创建尾插结点并尾插 */
    for (i = 0; i < 5; ++i)
    {
        pnode = CreateNode(data1[i]);
        if (NULL == pnode)
        {
            perror("fail to CreateNode");
            return -1;
        }
        PushTailNode(plist, pnode);
    }
#if 0
    /* 双向遍历 */
    SearchHeadAll(plist);
    printf("==========================\n");
    SearchTailAll(plist);
#endif
#if 0
    /* 查找对应id号的学生信息 */
    printf("==========================\n");
    printf("Input stu id to search:\n");
    scanf("%d", &uid);
    TWO_NODE *dest = SearchInLink(plist, uid);
    if (NULL == dest)
    {
        printf("NO STUDENT!\n");
    }
    else
    {
            printf("The Dest StuInfo:\nid = %d; name = %s; score = %d.\n", dest->data.id, dest->data.name, dest->data.score);
    }

#endif

#if 0
    /* 修改对应id号的学生信息 */
    DATA_STU sdata = {0};
    printf("==========================\n");
    printf("Input stu id to change:\n");
    scanf("%d", &sdata.id);
    printf("Input stu info to change:\nname:");
    scanf("%s", sdata.name);
    printf("score:");
    scanf("%d", &sdata.score);
    putchar('\n');

    ChangeInLink(plist, sdata.id, sdata);
    SearchHeadAll(plist);
#endif
#if 0
    /* 头删 */
    SearchHeadAll(plist);
    printf("==================================\n");
    PopHeadLink(plist);
    SearchHeadAll(plist);
#endif
#if 0
    /* 尾删 */
    SearchHeadAll(plist);
    printf("==================================\n");
    PopTailLink(plist);
    PopTailLink(plist);
    PopTailLink(plist);
    PopTailLink(plist);
    SearchHeadAll(plist);
#endif
#if 1
    /* 销毁 */
    SearchHeadAll(plist);
    printf("==================================\n");
    SearchTailAll(plist);
    DestroyLink(plist);

#endif
    return 0;
}

Makefile文件

all:doulink

doulink:main.c twolink.c
	gcc $^ -o $@

.PHONY:
clean:
	rm doulink;
	

作业:

12、删除双向链表指定结点

int DeleteIdNode(TWO_LIST *plist, int uid)
{
    TWO_NODE *dest = plist->phead;

    while (dest != NULL)
    {
        if (dest->data.id != uid)
        {
            dest = dest->pnext;
        }
        else
        {
            dest->ppre->pnext = dest->pnext;
            dest->pnext->ppre = dest->ppre;
            free(dest);
            plist->clen--;
        }
    }
    return 0;
}

 

13、双向链表倒置

int ReverseTwoLink(TWO_LIST *plist)
{
    TWO_NODE *ptmp = plist->phead;
    TWO_NODE *pver = NULL;
    struct node *p = NULL;

    if (plist->phead == NULL || plist->phead->pnext == NULL)
    {
        return -1;
    }

    while (ptmp->pnext != NULL)
    {
        ptmp = ptmp->pnext;
    }
    plist->phead = ptmp;
    while (ptmp != NULL)
    {
        pver = ptmp;
        ptmp = ptmp->ppre;
        p = pver->pnext;
        pver->pnext = pver->ppre;
        pver->ppre = p;
    }
    
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1532336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch 深度学习(GPT 重译)(六)

十四、端到端结节分析&#xff0c;以及接下来的步骤 本章内容包括 连接分割和分类模型 为新任务微调网络 将直方图和其他指标类型添加到 TensorBoard 从过拟合到泛化 在过去的几章中&#xff0c;我们已经构建了许多对我们的项目至关重要的系统。我们开始加载数据&#xf…

RK3399 android10 移植SiS-USB触摸驱动

一&#xff0c;SiS USB触摸简介 SiS USB 触摸屏通常是一种外接式触摸屏设备&#xff0c;通过 USB 接口连接到计算机或其他设备上。这种触摸屏设备可以提供触摸输入功能&#xff0c;用户可以通过手指或触控笔在屏幕上进行操作&#xff0c;实现点击、拖动、缩放等操作。 SiS USB…

腾讯云GPU云服务器简介_GPU服务器购买指南_GPU云服务器操作

腾讯云GPU服务器是提供GPU算力的弹性计算服务&#xff0c;腾讯云GPU服务器具有超强的并行计算能力&#xff0c;可用于深度学习训练、科学计算、图形图像处理、视频编解码等场景&#xff0c;腾讯云百科txybk.com整理腾讯云GPU服务器租用价格表、GPU实例优势、GPU解决方案、GPU软…

学点儿Java_Day7_在实体类当中IDEA无法进行单元测试(@Test没有启动按钮)

在敲代码体会继承和访问修饰符的时候忽然遇到了单元测试不管用的情况&#xff0c;表现为没有启动按钮   经过一番折腾&#xff0c;发现我的测试是在具有构造函数的实体类Person当中进行的&#xff0c;当我把所有的构造函数删除后&#xff0c;启动按钮又出来了&#xff0c;加…

Pycharm实用快捷键

Pycharm实用快捷键 1.代码/函数提示2.查找同一变量位置3.添加类型提示4.一键代码规范化5.任意位置切换到下一行6.快速运行7.多行快速注释8.展开/折叠代码块9.全局搜索10.变量用过的地方11.快速包围12.跳到文件成员13.在项目内查找14.快速选中15.导入优化16.扩展 / 缩小选中17.复…

【SQL】1141. 查询近30天活跃用户数(常规写法;date_add())

前述 mysql中date_add()函数的使用 题目描述 leetcode题目&#xff1a;1141. 查询近30天活跃用户数 Code 写法一 select activity_date as day, count(distinct user_id) as active_users from Activity where activity_date > 2019-06-27 and activity_date < 2019…

北斗短报文+4G应急广播系统:全面预警灾害信息 构建安全美好乡村

建设社会主义新农村是确保小康社会宏伟目标如期实现的必然要求&#xff0c;是构建和谐社会的重要内容。针对现代农业发展的要求&#xff0c;通过完善专业化监测预报技术&#xff0c;提高精细化的灾害监测预警能力&#xff0c;建设广覆盖的预警信息发布网络&#xff0c;建设有效…

Linux快速入门,上手开发 01.学习路线

少时曾许凌云志&#xff0c;当取世间第一流 再见少年拉满弓&#xff0c;不惧岁月不飓风 —— 24.3.20 1.Linux的发展历史 2.VM虚拟机的Linux初体验 3.图形化页面设置系统——快速上手 4.命令行操作——向专业前进 5.核心操作命令——必知必会&#xff08;管理企业级权限/定位b…

【web算法】列车车厢重排问题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

【Unity】Plastic云同步总是password error

【背景】 Plastic是Unity的项目版本控制功能&#xff0c;可以方便在多个地点同步项目进度。原本用得挺爽的&#xff0c;结果今天遇到糟心事&#xff0c;明明Hub也正常登着&#xff0c;可Plastic的一个update的dll就是不停反复运行并报Password invalid。 【问题分析】 听说I…

常见六大WEB安全问题

一、XSS跨站脚本攻击 1.Cross-Site Scripting&#xff08;跨站脚本攻击&#xff09;简称 XSS&#xff08;因为缩写和 CSS重叠&#xff0c;所以只能叫 XSS&#xff09;&#xff0c;是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本&#xff0c;使之在用户的浏览器上运行…

流畅的 Python 第二版(GPT 重译)(十)

第十八章&#xff1a;with、match 和 else 块 上下文管理器可能几乎与子例程本身一样重要。我们只是初步了解了它们。[…] Basic 有一个 with 语句&#xff0c;在许多语言中都有 with 语句。但它们的功能不同&#xff0c;它们都只是做一些非常浅显的事情&#xff0c;它们可以避…

关于v1.29.2 版本的Maxwell存在于mysql8.0后版本部分源码字符集处理确实问题

1. 先去GitHub下载源码.zip文件2. 找到上图中的这个 StringColumnDef.java 做如下修改 eg: 3.然后是pom文件部分的修改&#xff1a; 将这个org.jgroups的版本降低到0.5.2.Final 然后再去注释掉一个类的引用&#xff1a; MaxwellHA.java 3.1 还可以不用降低这个org.jgro…

大模型学习笔记七:LLM应用

文章目录 一、维护生产级别的LLM应用,需要做的事二、符合需求的LLM App维护平台三、LangFuse1)替换OpenAI客户端(把跟OpenAI交互记录到LangFuse)1.1)几个基本概念2)通过LangChain的回调函数触发记录(上面用的原生OpenAI接口,下面是调用LangChain的接口)3)构建一个实际…

3.20刷题--备赛ing

距离十五届蓝桥杯还有23天&#xff0c;奶奶的拼了。备赛ing 今天刷题 5道 有序分数递归方法 如何1/2 2/4都是相同的结果&#xff0c;但是需要的是1/2&#xff0c;如何解决这个问题呢&#xff0c;可以看出分子和分母约分最简的时候&#xff0c;他们的gcd1&#xff0c;所以求…

Socket类

2.2 Socket类 Socket 类&#xff1a;该类实现客户端套接字&#xff0c;套接字指的是两台设备之间通讯的端点。 构造方法 public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null &#xff0c;则相当于指定地址为回送…

【HTML】悄悄分享两个好玩的html代码

最近整理U盘资源&#xff0c;本来打算清理掉一些“无用”的文件&#xff0c;结果翻到了之前保存的一个保存着好玩代码的文件夹&#xff0c;默默点开了命名为"大佬做的html.html”这个文件&#xff08;谁还不是一个中二少年呢&#xff09;话不多说&#xff0c;上代码&#…

0301taildir-source报错-flume-大数据

1 基础环境简介 linux系统&#xff1a;centos&#xff0c;前置安装&#xff1a;jdk、hadoop、zookeeper、kafka&#xff0c;版本如下 软件版本描述centos7linux系统发行版jdk1.8java开发工具集hadoop2.10.0大数据生态基础组件zookeeper3.5.7分布式应用程序协调服务kafka3.0分…

成都正信晟锦:亲戚借了钱不认账怎么办是现金

在人际交往中&#xff0c;金钱往来往往是敏感而复杂的议题&#xff0c;尤其是与亲戚间的借贷。若遭遇亲戚借了钱却不认账的尴尬局面&#xff0c;我们该如何妥善处理呢? 沟通始终是解决问题的第一步。尝试与该亲戚进行坦诚的对话&#xff0c;了解不认账的原因。可能是对方遇到了…

基于springboot的车辆充电桩管理平台

技术&#xff1a;springbootmysqlvue 一、背景 科学技术日新月异的如今&#xff0c;计算机在生活各个领域都占有重要的作用&#xff0c;尤其在信息管理方面&#xff0c;在这样的大背景下&#xff0c;学习计算机知识不仅仅是为了掌握一种技能&#xff0c;更重要的是能够让它真正…