1、双链表

1.1 双向链表的声明

在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针.

声明

typedef struct NODE {
struct NODE *fwd;
struct NODE *bwd;
int value;
} Node;

根节点的fwd字段指向链表的第1个节点,根节点的bwd字段指向链表的最后一个节点.如果链表为空,这两个字段都为NULL.链表的第1个节点的bwd 字段和最后一个节点的 fwd 字段都为 NULL. 在一个有序的链表中,各个节点将根据value 字段的值以升序排列.

3.2 双向链表的插入

将一个新值插入到有序表中

函数原型

dll_insert( Node *rootp, int value );

dll_insert 接受两个参数,一个指向根节点的指针和一个整型值.

插入节点时,可能会遇到4中情况:

1、新值可能必须插入到链表的中间位置

2、新值可能必须插入到链表的起始位置

3、新值可能必须插入到链表的结束位置

4、新值可能必须既插入到链表的起始位置,又插入到链表的结束位置


/**
向双向链表中插入数据 @param rootp 根节点
@param value 带插入值
@return 0 已经有值, -1 不能插入, 1 插入成功
*/
int dll_insert( Dnode *rootp, int value) {
Dnode *this;
Dnode *next;
Dnode *newnode; //查看 value 是否已经存在于链表中, 如果是就返回.否则,为新值创建一个新节点(“newnode”将指向它)
//this 将指向应该在新节点之前的那个节点
//next 将指向应该在新节点之后的那个节点
for( this = rootp; (next = this->fwd) != NULL; this = next){
if (next->value == value) {
return 0;
}
if (next->value > value) {
break;
}
} newnode = (Dnode *)malloc( sizeof( Dnode) );
if ( newnode == NULL) {
return -1;
}
newnode->value = value; //把新值添加到链表中
if ( next != NULL) {
//情况 1,2 并非位于链表尾部.
if ( this != rootp ) {//情况1 并非位于链表起始位置
newnode->fwd = next;
this->fwd = newnode;
newnode->bwd = this;
next->bwd = newnode;
}else {// 情况2 位于起始位置
newnode->fwd = next;
this->fwd = newnode;
newnode->bwd = NULL;
next->bwd = newnode;
}
}else {
//情况3,4 位于链表的尾部
if (this != rootp) {// 情况3 并非位于链表的起始位置
newnode->fwd = NULL;
this->fwd = newnode;
newnode->bwd = this;
rootp->bwd = newnode;
}else {// 情况4 位于链表起始位置
newnode->fwd = NULL;
this->fwd = newnode;
newnode->bwd = NULL;
rootp->bwd = newnode;
}
} return 1;
}
//添加节点的4种情况可以提炼
if ( next != NULL) {
//情况1 或 2 并非位于链表的尾部
newnode->fwd = next;
if (this != rootp ) {//情况1 并非位于链表的起始位置
this->fwd = newnode;
newnode->bwd = this;
}else {//情况2 位于链表的起始位置
rootp->fwd = newnode;
newnode->bwd = NULL;
}
next->bwd = newnode;
}else {
//情况3或4 位于链表尾部
newnode->fwd = NULL;
if (this != rootp) {//情况3 并不位于链表起始位置
this->fwd = newnode;
newnode->bwd = this;
}else {//情况4 位于链表起始位置
rootp->fwd = newnode;
newnode->bwd = NULL;
}
rootp->bwd = newnode;
}

C和C指针小记(十八)-使用结构和指针-双向链表的更多相关文章

  1. C和C指针小记(十五)-结构和联合

    1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...

  2. 结构体与typedef的使用,还有结构体指针的使用(二层结构体指针)

    该类容摘抄自以下链接,为学习之后的记录,不是鄙人原创. 学习链接:https://blog.csdn.net/a2013126370/article/details/78230890 typedef ...

  3. Leetcode 2. Add Two Numbers(指针和new的使用)结构体指针

    ---恢复内容开始--- You are given two non-empty linked lists representing two non-negative integers. The di ...

  4. C和C指针小记(十六)-动态内存分配

    动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...

  5. C和C指针小记(十四)-字符串、字符和字节

    1.字符串 C语言没有字符串数据类型,因为字符串以字符串常量的形式出现或存储于字符数组中. 字符串常量和适用于那些程序不会对他们进行修改的字符串. 所有其他字符串都必须存储于字符串数组或动态分配的内存 ...

  6. C和C指针小记(十)-函数

    1.函数的定义 函数的定义就是函数体的实现. 语法: 类型 函数名(形式参数) 代码块 函数返回类型和函数名分开写是代码风格的问题,现代语言如swift返回值在函数名和参数表的后面,这样使得某些工程工 ...

  7. C和C指针小记(十二)-函数的可变参数表

    1.可变参数表是通过宏实现的 宏定义于stdarg.h头文件,它是标准库的一部分.这个头文件声明了一个类型var_list和三个宏--va_start.va_arg.va_end. 我们可以声明一个类 ...

  8. C和指针 第十二章 结构体 习题

    12.3 重新编写12.7,使用头和尾指针分别以一个单独的指针传递给函数,而不是作为一个节点的一部分 #include <stdio.h> #include <stdlib.h> ...

  9. C和指针 第十二章 结构体 整体赋值 error: expected expression

    定义结构体后整体赋值时发生错误 typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int value; } Node; //声明变量 ...

随机推荐

  1. SNF软件开发机器人-子系统-功能-启用大按钮样式如何配置

    启用大按钮 当启用大按钮被选中后,页面的按钮图表将以按钮配置中的大按钮样式显示. 1.效果展示: 2.使用说明: 打开显示页面,点击开发者选项的简单配置按钮.在功能表信息中选择启用大按钮复选框后保存.

  2. .NET Core+NLog+存储配置 日志存入到数据库

    nlog-config.xml 配置文件: <?xml version="1.0" encoding="utf-8" ?> <nlog xml ...

  3. 微信公众号平台上传文件返回错误代码:40005 invalid file type

    错误原因:文件类型(后缀名)不符合要求. 具体到笔者的情况是:在将 MultipartFile 类型转换为File 类型时,方法 File.createTempFile("filename& ...

  4. 【iCore4 双核心板_ARM】例程二十六:LWIP_MODBUS_TCP实验——电源监控

    实验现象: 核心代码: int main(void) { system_clock.initialize(); led.initialize(); adc.initialize(); delay.in ...

  5. 【CentOS-7+ Ambari 2.7.0 + HDP 3.0+HAWQ2.3.00】遭遇问题及解决记录

    一.zookeeper超出最大连接限制:ambari server检测到critical错误, zookeeper server on ep-bd01:2181 连接被积极拒绝,翻看主机上zookee ...

  6. Nginx 反向代理获取设备真实的IP地址

    package com.das.common.util; import org.apache.commons.lang3.StringUtils; import org.springframework ...

  7. Essay3.0发布,基于JavaScript的前后端同构博客系统

    前言 转眼间距离我开源这个项目已经两年了,最初是奔着学习的目的开发了这个项目,后来一直记录自己的学习笔记.随着时间的增长,发现之前写的代码简直不忍直视,于是就有了重构的想法.这个过程有些漫长,竟然用了 ...

  8. iOS开发之--Masonry多个平均布局

    使用Masonry平均布局,代码如下: 1.创建 // 图片组数 NSArray *imgAry = @[@"home_icon01",@"home_icon02&quo ...

  9. Kafka获取订阅某topic的所有consumer group【客户端版】

    之前写过如何用服务器端的API代码来获取订阅某topic的所有consumer group,参见这里.使用服务器端的API需要用到kafka.admin.AdminClient类,但是这个类在0.11 ...

  10. shell中uniq与sort -u 两种去重的对别

    sort -u 和 uniq都能起到删除重复信息的功能,那么他们的区别究竟在哪呢?$ cat test              jasonjasonjasonfffffjason 下面分别执行三个命 ...