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对象在第一 ...
随机推荐
- 反向代理:是指以代理server来接收Internet上的请求,然后将请求转发到内部网络的server上,并将结果返回给Internet上连接的client,此时的代理server对外就表现为反向代理server。
Nginx安装好之后.開始使用它来简单实现反向代理与负载均衡的功能.在这之前.首先得脑补一下什么是反向代理和负载均衡. 反向代理:是指以代理server来接收Internet上的请求,然后将 ...
- golang 操作 Redis & Mysql & RabbitMQ
golang 操作 Redis & Mysql & RabbitMQ Reids 安装导入 go get github.com/garyburd/redigo/redis import ...
- Java 之 assert (断言)
我们知道C/C++语言中有断言的功能(assert).在Java SE 1.4版本以后也增加了断言的特性. 断言是为了方便调试程序,并不是发布程序的组成部分.理解这一点是很关键的. 默认情况下,JVM ...
- sql中group by用来干嘛的
sql中group by用来干嘛的 一.总结 一句话总结: 1.group by用来分类汇总的,by后面接要分的类 2.group by既然是分类汇总,那就要和聚合函数结合使用,因为要汇总啊 3.ha ...
- wpf datagrid 的单元格内容超出列宽度
---恢复内容开始--- <Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.mi ...
- rebar工具使用备忘录
http://cryolite.iteye.com/blog/1159448 rebar是一个开源的erlang应用自动构建工具.basho的tuncer开发.它实际上是一个erlang脚本(escr ...
- java中的方法返回值使用泛型,实现灵活的返回值类型
痛点: 使用Mybatis框架的时候,想封装一个底层JDBC控制器,用于提供和Mybatis交互的增删改查接口(公用的接口),但由于公用的查询方法可能是用户自定义的任意一个和表对应的java ...
- 简单的记录一下JavaScript 高级应用
我是一名.net 程序员但是由于公司需求,开发离线app,但是在工作的过程中我发现,周围人在写JavaScript的时候都是面向过程的编码,对于我这.net程序员,遇到这种情况真是六神无主,但是工作中 ...
- jsp中国文字形式提交,request对象获取乱码
jsp表单提交中文字符,request对象获取时乱码解决方法 第一种: 在request对象获取页面Charset中的"C"大写,且页面无中文字符,最好用英文,否则MyEclips ...
- 【从翻译mos文章】采用高速全扫描索引(index ffs) 为了避免全表扫描
采用高速全扫描索引(index ffs) 为了避免全表扫描 参考原始: Index Fast Full Scan Usage To Avoid Full Table Scans (Doc ID 701 ...