C和指针 (pointers on C)——第十二章:利用结构和指针
第十二章 利用结构和指针
这章就是链表。先单链表,后双向链表。
总结:
单链表是一种使用指针来存储值的数据结构。链表中的每一个节点包括一个字段,用于指向链表的下一个节点。
有一个独立的根指针指向链表的第1个节点。
单链表仅仅能从一个方向遍历。
怎样insert单链表:1、新节点的link字段必须设置为指向它的后面节点。
2、前一个节点的link字段必须指向这个新节点。
为了防止可能会插入链表的起始位置这样的情况,在C中,能够保存一个指向必须进行改动的link字段的指针。而不是保存一个指向前一个节点的指针。
双链表中的每一个节点包括两个link字段:当中一个指向链表的下一个node。还有一个指向前一个node。
双链表有两个根指针,一个指向第一个node,还有一个指向最后一个node。因此遍历的过程中能够从不论什么一端開始。并且在遍历过程中够能够改变方向。
为了把一个新节点插入到双链表中。我们必须改动4个指针。新节点的前向和后向link字段必需被设置,前一个节点的fwd和后一个节点的bwd也要改动,指向新节点。
警告:
1、落到链表尾部的后面。
2、使用指针时应该格外小心。由于C并没有对他们的使用提供安全网。
3、从if语句中提炼语句可能会改变測试结果。
编程提示:
1、消除特殊情况使代码更易于维护。
2、不要轻易的进行提炼语句,这样会使你的语句更难维护。
编程实例:(本章就不再弄习题了,关于数据结构这块会有大量代码进行训练)
1、提炼后的单链表插入操作
#include "stdlib.h" typedef struct NODE
{
struct NODE *link;
int value;
} Node;
int sll_int(register Node **linkp, int new_value)
{
register Node *current; //指向当前节点
register Node *new_node; //指向插入节点 /*
** 寻找正确插入位置,按顺序訪问链表,直到有个值大于或等于新值
*/
while ((current = current->link) != NULL && current->value < new_value)
{
linkp = ¤t->link; //移动linkp指向下一个Node的link
}
/* 分配新的内存,并存到新节点去 */
new_node = (NODE *) malloc (sizeof(NODE));
if (new_node == NULL)
{
return 0;
}
new_node->value = new_value;
/* 插入新节点 */
new_node->link = current;
*linkp = new_node;
return 1;
}
2、双链表插入操作
#include "stdlib.h" typedef struct NODE
{
struct NODE *fwd;
struct NODE *bwd;
int value;
}Node; int dll_insert(Node *rootp, int value)
{
/* 把一个值插入到一个双向链表中。rootp是一个指向根节点的指针
value 是插入的新值
返回值:假设已经存在链表中。返回0
假设内存不足导致无法插入,返回-1,成功返回1;
*/
Node *this_node;
Node *next_node;
Node *new_node; for (this_node = rootp; next_node != NULL; this_node = next_node )
{
if (next_node->value == value)
return 0;
if (next_node->value < value)
break;
next_node = next_node->fwd;
}
/* 为新节点申请内存空间*/
new_node = (Node *) malloc (sizeof(Node));
if (new_node == NULL)
return -1;
new_node->value = value;
/*
插入节点
if 不在链表尾部 then 不在链表起始位置 or 位于链表起始位置
else 在链表尾部 then 不在链表起始位置 or 位于链表起始位置(空链表)
*/
if (next_node->fwd != NULL)
{
/*不在链表尾部*/
if (this_node != rootp)
{
/* 不在链表的头部 */
this_node->fwd = new_node;
next_node->bwd = new_node;
new_node->bwd = this_node;
new_node->fwd = next_node;
}
else
{
/* 在链表的头部*/
rootp->fwd = new_node;
next_node->bwd = new_node;
new_node->bwd = rootp;
new_node->fwd = next_node;
}
}
else
{
/*在链表尾部*/
if (this_node->bwd != rootp)
{
/* 不在链表的头部 */
new_node->fwd = NULL;
new_node->bwd = this_node;
this_node->fwd = new_node;
rootp->bwd = new_node;
}
else
{
/* 在链表的头部*/
new_node->fwd = NULL;
new_node->bwd = NULL;
rootp->bwd = new_node;
rootp->fwd = new_node;
}
} }
版权声明:本文博客原创文章,博客,未经同意,不得转载。
C和指针 (pointers on C)——第十二章:利用结构和指针的更多相关文章
- C和指针 第十二章 使用结构和指针 双链表和语句提炼
双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况: 1.插入到链表头部 2.插入到链表尾部 3.插入到空链表中 4.插入到链表内部 #include <stdio ...
- C和指针 第十二章 使用结构和指针
链表是一种常用的数据结构,每个节点通过链或者指针链接在一起,程序通过间接指针访问链表中的节点. typedef struct Node { //指向下一个节点的指针 struct Node *next ...
- 《Linux命令行与shell脚本编程大全》第十二章 使用结构化命令
许多程序要就对shell脚本中的命令施加一些逻辑控制流程. 结构化命令允许你改变程序执行的顺序.不一定是依次进行的 12.1 使用if-then语句 如下格式: if command then ...
- perl5 第十二章 Perl5中的引用/指针
第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用 子程序模板七.数组与子程序八.文件句 ...
- [CSAPP笔记][第十二章并发编程]
第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...
- C primer plus 第五版十二章习题
看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: /* global.c --- 使用外部变量 ...
- 《OpenCL异构并行编程实战》补充笔记散点,第五至十二章
▶ 第五章,OpenCL 的并发与执行模型 ● 内存对象与上下文相关而不是与设备相关.设备在不同设备之间的移动如下,如果 kernel 在第二个设备上运行,那么在第一个设备上产生的任何数据结果在第二个 ...
- 第十二章 Python文件操作【转】
12.1 open() open()函数作用是打开文件,返回一个文件对象. 用法格式:open(name[, mode[, buffering[,encoding]]]) -> file obj ...
- 【C++】《C++ Primer 》第十二章
第十二章 动态内存 目前为止,所使用的对象都有着严格定义的生存期. 全局对象在程序启动时分配,在程序结束时销毁.局部自动对象在进入其定义所在的程序块时被创建,在离开块时销毁.局部static对象在第一 ...
随机推荐
- Jedis 源代码阅读一 —— Jedis
这是jedis 源代码文件夹,我们接下来选择性阅读重要的接口以及实现. └─redis └─clients ├─jedis │ │ BinaryClient.java │ │ BinaryJedis. ...
- MinGW和MSYS项目是在一起的(翻译官网)
翻译MinGW官网的首页,首页描述了MinGW和MSYS的基本情况. Home of the MinGW and MSYS Projects(我才知道,MinGW和MSYS项目是在一起的 -_-!) ...
- SelectionKey API 用法
java.nio.channels 类 SelectionKey java.lang.Object java.nio.channels.SelectionKey 直接已知子类: AbstractSel ...
- MinGW 与MSVC的区别
Qt 中有两种方式编译,一种是MinGW ,另一种MSVC. 其中:MSVC是指微软的VC编译器 MingGW是指是Minimalist GNU on Windows的缩写.它是一个可自由使用和自由发 ...
- Notepad++打开xml文件显示crlf的问题
如图所示,显示CRLF, CRLF其实是换行符. 所以在下图所示设置下显示行尾符不显示即可.
- Android菜鸟的成长笔记(27)——SurfaceView的使用
前面有关自定义View中进行了绘图,但View的绘图机制存在如下缺陷: 1.View缺乏双缓冲机制. 2.当程序需要更新View上的图像时,程序必须重绘View上显示的整张图片. 3.新线程无法直接更 ...
- Http请求工具类(Java原生Form+Json)
package com.tzx.cc.common.constant.util; import java.io.IOException; import java.io.InputStream; imp ...
- eclipse使用Hibernate tools反向工程插件遇到的几个问题
1,在eclipse使用hibernate工具,生成hibernate配置文件时,可能会提示not parse ....xml错误 参见 加载本地dtd 2,反向工程中,生成配置文件时,一般要填写其默 ...
- 灵活使用Excel可能会提高Java代码编写效率
使用Java操作数据时,当表字段太多时,书写实体类和进行实体类对象操作时都是一个繁重且易错的工作,光靠复制粘贴快捷键已不能满足负责的操作. 首先,说一下,就是在Eclipse中的快捷键,小写:ctrl ...
- leveldb学习:skiplist
leveldb中的memtable仅仅是一个封装类,它的底层实现是一个跳表. 跳表是一种基于随机数的平衡数据结构.其它的平衡数据结构还有红黑树.AVL树.但跳表的原理比它们简单非常多.跳表有点像链表, ...