C和C指针小记(十八)-使用结构和指针-双向链表
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指针小记(十八)-使用结构和指针-双向链表的更多相关文章
- C和C指针小记(十五)-结构和联合
1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...
- 结构体与typedef的使用,还有结构体指针的使用(二层结构体指针)
该类容摘抄自以下链接,为学习之后的记录,不是鄙人原创. 学习链接:https://blog.csdn.net/a2013126370/article/details/78230890 typedef ...
- Leetcode 2. Add Two Numbers(指针和new的使用)结构体指针
---恢复内容开始--- You are given two non-empty linked lists representing two non-negative integers. The di ...
- C和C指针小记(十六)-动态内存分配
动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...
- C和C指针小记(十四)-字符串、字符和字节
1.字符串 C语言没有字符串数据类型,因为字符串以字符串常量的形式出现或存储于字符数组中. 字符串常量和适用于那些程序不会对他们进行修改的字符串. 所有其他字符串都必须存储于字符串数组或动态分配的内存 ...
- C和C指针小记(十)-函数
1.函数的定义 函数的定义就是函数体的实现. 语法: 类型 函数名(形式参数) 代码块 函数返回类型和函数名分开写是代码风格的问题,现代语言如swift返回值在函数名和参数表的后面,这样使得某些工程工 ...
- C和C指针小记(十二)-函数的可变参数表
1.可变参数表是通过宏实现的 宏定义于stdarg.h头文件,它是标准库的一部分.这个头文件声明了一个类型var_list和三个宏--va_start.va_arg.va_end. 我们可以声明一个类 ...
- C和指针 第十二章 结构体 习题
12.3 重新编写12.7,使用头和尾指针分别以一个单独的指针传递给函数,而不是作为一个节点的一部分 #include <stdio.h> #include <stdlib.h> ...
- C和指针 第十二章 结构体 整体赋值 error: expected expression
定义结构体后整体赋值时发生错误 typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int value; } Node; //声明变量 ...
随机推荐
- Android Activity的4种启动模式
Activity的启动模式 standard 默认标志的启动模式,每次startActivity都是创建一个新的activity的实例,适用于绝大数情况 singleTop 单一顶部,如果要开启的ac ...
- 正则双重过滤 /// splitKey1 第一个正则式匹配 /// splitKey2 匹配结果中再次匹配进行替
/// <summary> /// 正则双重过滤 /// splitKey1 第一个正则式匹配 /// splitKey2 匹配结果中再次匹配进行替换 /// </summary&g ...
- 中期linux课程考试题
[口头表达] 1)请描述你了解的磁盘分区的相关知识2)什么是rsync,你有什么生产环境的应用?3)在生产环境中,公司的IDC机房即将超过254台机器,请问你有什么解决方案来规划扩展IDC机房的内网网 ...
- CentOS 安装 Redis 5
https://redis.io/download下载最新stable版,当前最新版为redis-5.0.3.tar.gz cd /usr/local/src && wget http ...
- .NET HttpPost 上传文件图片到服务器
public class ImageData { public string imageFilePath { get; set; } public string tempFilePath { get; ...
- Ubuntu 安装显卡驱动
首先到英伟达的官网下载最新的驱动 然后,首先要卸载Ubuntu上已有的显卡驱动 $ sudo apt-get purge nvidia* 然后仅用Ubuntu自带的显卡驱动nouveau,不过我的16 ...
- SudaMod-81.0 / crDroidAndroid-8.1(android-8.1.0_r20)红米3 2018年5月3日更新
一.写在前面 我只是个人爱好,本ROM未集成任何第三方推广软件,我只是喜欢把好的资源分享出来,若可以,我们一起学习,一起进步. 请不要问我怎么刷机! 请不要问我玩游戏卡不卡(有钱你就换好点的手机)! ...
- 解决wps/office 1-2自动转换1月2日,用样式解决此问题
添加样式: td{mso-number-format:"\@"; }
- 在Android中使用FFmpeg(android studio环境)
1.首先我们需要一个已经编译好的libffmpeg.so文件.(怎么编译是个大坑,可以参考windows环境下编译android中使用的FFmpeg,也可以用网上下载的现成的,本文相关的github项 ...
- Linux 相关术语_002
Linux(Linux is not unix)是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统. 它能运行主要的UNIX工 ...