当前位置: 首页 > ops >正文

数据结构——双向链表

双向链表的结构:

在这里插入图片描述

双向链表由链表对象,头结点,中间结点以及尾结点组成每一部分结点结构或是指针内容存在差异,需要牢记双向链表的结构,双向链表的结构使我们能够通过一个中间节点找到它前后的结点,这是与单向链表的最大区别。

需要熟练掌握的基本操作:

在这里插入图片描述

让我们在记牢理解双向链表的结构以后直接上代码练习

封装双向链表:1:头文件定义双向链表的结构

#ifndef __DOULINK_H__
#define __DOULINK_H__
//双向链表存储的数据类型
typedef struct stu
{int id;char name[32];int score;
}Data_type_t;/*双向链表的结点类型*/
typedef struct dounode
{Data_type_t data;struct dounode *ppre;  //指向前驱结点的指针struct dounode *pnext; //指向后继结点的指针
}DNode_t;/*双向链表对象类型*/
typedef struct doulink
{DNode_t *phead;   //双向链表头结点地址int clen;         //双向链表结点个数
}DLink_t;
extern DLink_t *create_doulink();
extern int insert_doulink_head(DLink_t *pdlink, Data_type_t data);
extern int is_empty_doulink(DLink_t *pdlink);
extern void doulink_for_each(DLink_t *pdlink, int dir);
extern int insert_doulink_tail(DLink_t *pdlink, Data_type_t data);
extern int delete_doulink_head(DLink_t *pdlink);
extern int delete_doulink_tail(DLink_t *pdlink);

使用头插法构建双向链表:头插法是重点

#include "doulink.h"
#include <stdio.h>
#include <stdlib.h>DLink_t *create_doulink()
{DLink_t *pdlink= malloc(sizeof(DLink_t));if (NULL == pdlink){printf("malloc error");return NULL;}pdlink->phead = NULL;pdlink->clen = 0;return pdlink;
}int is_empty_doulink(DLink_t *pdlink)
{return NULL == pdlink->phead;}int insert_doulink_head(DLink_t *pdlink, Data_type_t data)
{DNode_t *pnode = malloc(sizeof(DNode_t));if (NULL == pnode){printf("malloc error");return -1;}pnode->data = data;pnode->ppre = NULL;pnode->pnext = NULL;if (is_empty_doulink(pdlink)){pdlink->phead = pnode;}else{pnode->pnext = pdlink->phead;pdlink->phead->ppre = pnode;pdlink->phead = pnode;}pdlink->clen++;return 0;
}

主函数部分:

#include <stdio.h>
#include "doulink.h"int main(void)
{Data_type_t stus[5] = {{1, "zhangsan", 99},{2, "lisi", 100}, {3, "wangwu", 90}, {4, "maliu", 56}, {5, "tianqi", 66}};DLink_t *pdlink = create_doulink();if (NULL == pdlink){return -1;}insert_doulink_head(pdlink, stus[0]);insert_doulink_head(pdlink, stus[1]);insert_doulink_head(pdlink, stus[2]);insert_doulink_tail(pdlink, stus[3]);insert_doulink_tail(pdlink, stus[4]);

构建好双向链表后,对于双向链表的各种基本操作:

遍历打印:dir1顺序打印,direlse逆序打印

void doulink_for_each(DLink_t *pdlink, int dir)
{if (is_empty_doulink(pdlink)){return ;}DNode_t *ptmp = pdlink->phead;if (dir){while (ptmp != NULL){printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);ptmp = ptmp->pnext;}}else{while (ptmp->pnext != NULL){ptmp = ptmp->pnext;}while (ptmp != NULL){printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);ptmp = ptmp->ppre;}}printf("\n");
}

尾插法

int insert_doulink_tail(DLink_t *pdlink, Data_type_t data)
{DNode_t *pnode = malloc(sizeof(DNode_t));if (NULL == pnode){printf("malloc error\n");return -1;}pnode->data = data;pnode->ppre = NULL;pnode->pnext = NULL;if (is_empty_doulink(pdlink)) //空链表情况{pdlink->phead = pnode;}else //非空链表情况{DNode_t *ptmp = pdlink->phead;while (ptmp->pnext != NULL){ptmp = ptmp->pnext;}ptmp->pnext = pnode;pnode->ppre = ptmp;}pdlink->clen++;return 0;
}

删除头结点:

int delete_doulink_head(DLink_t *pdlink)
{if (is_empty_doulink(pdlink)){return -1;}DNode_t *pdel = pdlink->phead;pdlink->phead = pdel->pnext;if (pdlink->phead != NULL){pdlink->phead->ppre = NULL;}free(pdel);pdlink->clen--;return 0;
}

删除尾结点:

int delete_doulink_tail(DLink_t *pdlink)
{if (is_empty_doulink(pdlink)){return -1;}DNode_t *ptmp = pdlink->phead;if (1 == pdlink->clen){free(ptmp);pdlink->phead = NULL;}else{while (ptmp->pnext != NULL){ptmp = ptmp->pnext;}ptmp->ppre->pnext = NULL;free(ptmp);}pdlink->clen--;return 0;
}

销毁链表

int destory_dblink(dbLINK_T *plink)
{if(is_empty_doubleLink(plink)){printf("空结点");return -1;}dbNODE_T *p=plink->phead;while(p!=NULL){p=p->pnext;head_node_delet(plink);}free(plink);return 0;}

== 这个销毁方法无法销毁主函数里面创造的plink==,,这时我们使用二级指针销毁主函数以及封装函数里的双向链表

在这里插入图片描述

查找结点并返回其地址

dbNODE_T *findnode(dbLINK_T *plink,char name[20])
{if(is_empty_doubleLink(plink)){printf("空链表,无结点可查");return NULL;}dbNODE_T *p=plink->phead;while (p!=NULL){if(strcmp(p->data.name,name)==0){return p;}p=p->pnext;}printf("查找不到该学生");    return NULL;
}

根据名字修改学生分数

int findnodeAndChangeScore(dbLINK_T *plink,char name[20],int newscore)
{if(is_empty_doubleLink(plink)){printf("空链表,无结点可查");return -1;}dbNODE_T *p=plink->phead;while (p!=NULL){if(strcmp(p->data.name,name)==0){p->data.score=newscore;return 0;}p=p->pnext;}printf("查找不到该学生");    return -1;
}

查找结点并删除该结点:

int findnodeAndDELETnode(dbLINK_T *plink, char name[20])
{if(is_empty_doubleLink(plink)){printf("空链表,无结点可查\n");return -1;}dbNODE_T *p = plink->phead;// 遍历整个链表查找节点while (p != NULL){if(strcmp(p->data.name, name) == 0){// 情况1:删除头节点if(p->ppre == NULL){head_node_delet(plink);}// 情况2:删除尾节点else if(p->pnext == NULL){p->ppre->pnext = NULL;free(p);plink->clen--;}// 情况3:删除中间节点else{p->ppre->pnext = p->pnext;p->pnext->ppre = p->ppre;free(p);plink->clen--;}printf("找到并删除该学生节点\n");return 0;}p = p->pnext;}// 遍历完未找到节点printf("无法找到该同学,无法删除结点\n");return -1;
}

主函数

#include<stdio.h>
#include"doublelink.h"
int main(void)
{STUDENT_T stus[5]={{1,"zhangsan",99},{2,"lisi",100},{3,"wangwu",90},{4,"maliu",56},{5,"tianqi",66}};dbLINK_T *plink=creatlink(plink);if(plink==NULL){printf("mallol error");return -1;}creat_db_NODE(plink,stus[0]);creat_db_NODE(plink,stus[1]);creat_db_NODE(plink,stus[2]);creat_db_NODE(plink,stus[3]);creat_db_NODE(plink,stus[4]);/*  insert_dblink_tail(plink,stus[4]);leach_dblink(plink,1);head_node_delet(plink);deletLink_fromTheLastNODE(plink);*/leach_dblink(plink,1);/*  dbNODE_T *ret=findnode(plink,"wangwu");if(ret==NULL){return -1;}printf("学生名:%p\n",ret);*//*  findnodeAndChangeScore(plink,"lisi",50);leach_dblink(plink,1);*/findnodeAndDELETnode(plink,"wangwu");leach_dblink(plink,1);destory_dblink(plink);//  leach_dblink(plink,0);return 0;
}
http://www.xdnf.cn/news/17080.html

相关文章:

  • Linux 调度器函数sched_*系统调用及示例
  • 【音视频】WebRTC 一对一通话-信令服
  • Go语言实战案例:使用context控制协程取消
  • 算法训练之哈希表
  • Java后端高频面试题
  • React在使用create-react-app创建项目慢的解决办法
  • python的高校考研交流系统
  • 基于ARM+FPGA多通道超声信号采集与传输系统设计
  • 广州客户 戴尔R720服务器 liunx系统 RAID5无损升级扩容
  • 注意点:Git 从安装到分支协作、冲突解决的完整步骤 ---待修改,没看这个步骤,需要重新整理步骤
  • JavaWeb(苍穹外卖)--学习笔记17(Websocket)
  • 国产三防平板电脑是什么?三防平板推荐
  • 前端包管理器深度对比
  • VUE2 学习笔记18 路由守卫
  • Mysql使用Canal服务同步数据->ElasticSearch
  • 数据挖掘,到底是在挖掘什么?
  • Golang 基本数据类型
  • 智慧工业复杂目标检测精度跃升:陌讯多模态融合算法实战解析
  • mac前端环境安装
  • 机器学习之KNN、贝叶斯与决策树算法
  • 自动驾驶控制算法——MPC控制算法
  • 浮雕软件Artcam安装包百度云网盘下载与安装指南
  • Redis(六):分布式锁
  • 【机器学习深度学习】 知识蒸馏
  • 分布式网关技术 + BGP EVPN,解锁真正的无缝漫游
  • Java面试宝典:深入解析JVM运行时数据区
  • 计算机网络:(十三)传输层(中)用户数据报协议 UDP 与 传输控制协议 TCP 概述
  • python+MySQL组合实现生成销售财务报告
  • AI的第一次亲密接触——你的手机相册如何认出你的猫?
  • QUdpSocket发送组播和接受组播数据