C和指针 第十二章 使用结构和指针 双链表和语句提炼
双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况:
1、插入到链表头部
2、插入到链表尾部
3、插入到空链表中
4、插入到链表内部
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0 //指针fwd指向前一个节点,bwd指向后一个节点
typedef struct NODE {
struct NODE *fwd;
struct NODE *bwd;
int value;
} Node; //插入value到双链表中,rootPtr为指向节点的指针
int doubleLinklistInsert(Node *rootPtr, int value)
{
Node *this;
Node *next;
Node *newNode; for(this = rootPtr; (next = this -> fwd) != NULL; this = next){
//如果节点值已经存在
if(next -> value == value){
return FALSE;
}
//找到插入位置
if(next -> value > value){
break;
}
} //分配内存
newNode = (Node *)malloc(sizeof(Node));
if(newNode == NULL){
return FALSE;
} newNode -> value = value; /*插入节点一共四种情况
1.插入到头部
2.插入到尾部
3.插入到中间
4.插入到空链表中
*/
//如果插入到头部部或者内部
if(next != NULL){
//插入到内部
if(this != rootPtr){
newNode -> fwd = next;
newNode -> bwd = this;
this -> fwd = newNode;
next -> bwd = newNode;
}else{
//插入到头部,newNode的bwd为NULL
newNode -> fwd = next;
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
next -> bwd = newNode;
}
}else{
//插入到尾部或者空表中
if(this != rootPtr){
//插入到尾部,修改根指针的bwd和fwd
newNode -> fwd = NULL;
newNode -> bwd = this;
this -> fwd = newNode;
rootPtr -> bwd = newNode;
}else{
//插入到空链表中
newNode -> fwd = NULL;
newNode -> bwd = NULL;
this -> fwd = newNode;
this -> bwd = newNode;
}
} return TRUE;
} int main()
{
Node third;
Node second;
Node first; third = (Node){NULL, &second, 4};
second = (Node){&third, &first, 2};
first = (Node){&second, NULL, 1}; Node root = {&first, &third, -1};
Node *rootPtr = &root; doubleLinklistInsert(rootPtr, 35);
doubleLinklistInsert(rootPtr, -10);
doubleLinklistInsert(rootPtr, 3); rootPtr = &root;
while((rootPtr = rootPtr -> fwd) != NULL){
printf("%d\t", rootPtr -> value);
}
return 0;
}
运行:

优化:
1.语句提炼
对于下面的代码可以从if语句中,提取出共同的部分。
if(x = 3){
i = 1;
something;
}else{
i = 1;
something different;
}
将共同的i=1,提取出if语句
i = 1;
if(x = 3){
something;
}else{
something different;
}
代码提炼:提取共同项
if(next != NULL){
newNode -> fwd = next;
next -> bwd = newNode;
//插入到内部
if(this != rootPtr){
newNode -> bwd = this;
this -> fwd = newNode;
}else{
//插入到头部,newNode的bwd为NULL
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
}
}else{
//插入到尾部或者空表中
newNode -> fwd = NULL;
this -> fwd = newNode;
if(this != rootPtr){
//插入到尾部,修改根指针的bwd和fwd
newNode -> bwd = this;
rootPtr -> bwd = newNode;
}else{
//插入到空链表中
newNode -> bwd = NULL;
this -> bwd = newNode;
}
}
对于下面的情况
if(field!= NULL){
pointer = field;
}else{
pointer=NULL;
}
//第二种情况field等于NULL,所以上面条件语句可以写成
pointer =field;
要找出看起来虽然不一样,但逻辑上是相同的代码,进行简化,这里第二个else中this此时是等于rootPtr的,所以相同, this转换成rootPtr,然后提取出。提取之后两个条件语句中都有:
if(this != rootPtr){
//插入到尾部,修改根指针的bwd和fwd
newNode -> bwd = this;
this -> fwd = newNode;
}else{
//插入到空链表中
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
}
提取出来:
if(this != rootPtr){
//插入到尾部,修改根指针的bwd和fwd
newNode -> bwd = this;
this -> fwd = newNode;
}else{
//插入到空链表中
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
}
if(next != NULL){
newNode -> fwd = next;
next -> bwd = newNode;
//插入到内部
}else{
//插入到尾部或者空表中
newNode -> fwd = NULL;
rootPtr -> bwd = newNode;
}
下面的第二个else中的next是NULL,所以NULL可以转换一下,继续提取出来:
newNode -> fwd = next;
if(next != NULL){
next -> bwd = newNode;
}else{
rootPtr -> bwd = newNode;
} if(this != rootPtr){
newNode -> bwd = this;
this -> fwd = newNode;
}else{
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
}
提取出来,最终简化版:
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0 //指针fwd指向前一个节点,bwd指向后一个节点
typedef struct NODE {
struct NODE *fwd;
struct NODE *bwd;
int value;
} Node; //插入value到双链表中,rootPtr为指向节点的指针
int doubleLinklistInsert(Node *rootPtr, int value)
{
Node *this;
Node *next;
Node *newNode; for(this = rootPtr; (next = this -> fwd) != NULL; this = next){
//如果节点值已经存在
if(next -> value == value){
return FALSE;
}
//找到插入位置
if(next -> value > value){
break;
}
} //分配内存
newNode = (Node *)malloc(sizeof(Node));
if(newNode == NULL){
return FALSE;
} newNode -> value = value; /*插入节点一共四种情况
1.插入到头部
2.插入到尾部
3.插入到中间
4.插入到空链表中
*/
//如果插入到头部部或者内部 newNode -> fwd = next;
if(next != NULL){
next -> bwd = newNode;
}else{
rootPtr -> bwd = newNode;
} if(this != rootPtr){
newNode -> bwd = this;
this -> fwd = newNode;
}else{
newNode -> bwd = NULL;
rootPtr -> fwd = newNode;
} return TRUE;
} int main()
{
Node third;
Node second;
Node first; third = (Node){NULL, &second, 4};
second = (Node){&third, &first, 2};
first = (Node){&second, NULL, 1}; Node root = {&first, &third, -1};
Node *rootPtr = &root; doubleLinklistInsert(rootPtr, 35);
doubleLinklistInsert(rootPtr, -10);
doubleLinklistInsert(rootPtr, 3); rootPtr = &root;
while((rootPtr = rootPtr -> fwd) != NULL){
printf("%d\t", rootPtr -> value);
}
return 0;
}
运行:

通过提炼语句,消除if语句中的重复语句。
C和指针 第十二章 使用结构和指针 双链表和语句提炼的更多相关文章
- C和指针 第十二章 使用结构和指针
链表是一种常用的数据结构,每个节点通过链或者指针链接在一起,程序通过间接指针访问链表中的节点. typedef struct Node { //指向下一个节点的指针 struct Node *next ...
- 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; //声明变量 ...
- 《Linux命令行与shell脚本编程大全》第十二章 使用结构化命令
许多程序要就对shell脚本中的命令施加一些逻辑控制流程. 结构化命令允许你改变程序执行的顺序.不一定是依次进行的 12.1 使用if-then语句 如下格式: if command then ...
- C和指针 (pointers on C)——第十二章:利用结构和指针
第十二章 利用结构和指针 这章就是链表.先单链表,后双向链表. 总结: 单链表是一种使用指针来存储值的数据结构.链表中的每一个节点包括一个字段,用于指向链表的下一个节点. 有一个独立的根指针指向链表的 ...
- 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 在第二个设备上运行,那么在第一个设备上产生的任何数据结果在第二个 ...
随机推荐
- 用U盘安装Ubuntu系统
用U盘安装Ubuntu,需制作一个Ubuntu的U盘安装盘,最为方便和可靠的制作方法是在Linux系统下使用dd命令,具体如下, sudo dd if=ubuntu-14.04.4-server-am ...
- UVA 11859 Division Game[Nim游戏]
题意:给定一个N*M的矩阵,每次可以选择同一行中的若干个数,把它们变成它们的质因子.问说先手的可否获胜. 同一行相当于1堆,数量就是所有数的质因子个数之和 #include <iostream& ...
- [USACO14OPEN] Dueling GPS's[最短路建模]
题目描述 Farmer John has recently purchased a new car online, but in his haste he accidentally clicked t ...
- 洛谷10月月赛Round.1| P3398 仓鼠找sugar[LCA]
题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...
- http协议进阶(三)http报文
一.报文流 http报文是在http应用程序之间发送的数据块(也可称为数据包).这些数据块以一些文本的元信息(meta-information)开头,描述了报文的内容及含义,后面跟着 可选的数据部分, ...
- Netron开发快速上手(一):GraphControl,Shape,Connector和Connection
版权所有,引用请注明出处:<<http://www.cnblogs.com/dragon/p/5203663.html >> 本文所用示例下载FlowChart.zip 一个用 ...
- 订餐系统之Excel批量导入
批量导入现在基本已经成为各类系统的标配了,当前,我们订餐系统也不例外,什么商家呀.商品呀.优惠码之类的,都少不了.毕竟嘛,对非开发人员来说,看到Excel肯定比看到很多管理系统还是要亲切很多的.这里, ...
- DayPilot 7.9.3373 去掉DEMO
更新升级倒是蛮快的,多了Gantt图,此处下载先: http://files.cnblogs.com/files/pccai/DayPilot_2.0_4.0_7.9.3373.rar
- 招聘前端、Java后端开发、测试、Mysql DBA
公司介绍: http://www.lagou.com/gongsi/43095.html http://www.yamichu.com 简历发到: zhuye@yamichu.com 招聘职位: JA ...
- .Net Core Linux centos7行—vscode开发,linux部署运行
前面搭建好啦linux运行环境,下面搭建windows下的开发环境.并完成调试 参考地址:https://www.microsoft.com/net/core#windows. 按照步骤来就好.安装. ...