以下是本人对双向链表的相关操作及相应的代码优化学习笔记
1 双向链表的插入有4种情况:
1.1 插入到链表的开始位置
1.2 插入到链表的中间位置
1.3 插入到链表的结束位置
1.4 链表为空,既插入到开始位置 同时也插入到结束位置。
1.5 以下是双向链表的示意图:
根据分析,写出代码如下:
代码 1 :
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
struct node *prev;
struct node *next;
int value;
}Node;
Node *create_node(int value)
{
Node *root =(Node *)malloc(sizeof(Node));
if (root == NULL)
return 0;
root->next = NULL;
root->prev = NULL;
root->value = value;
return root;
}
//此链表有头结点,头结点的prev next 指针分别
//指向第一个结点和最后一个结点
int list_insert1(Node *root,int value)
{
Node *this;
Node *that;
Node *new;
for (this = root;(that = this->next)!=NULL;
this = that) {
if (that->value == value){
return 1;
}
if (that->value > value) {
break;
}
}
//跳出for循环的条件是找到了待插入的结点
//或则是一直没有找到,知道遍历到链表末尾
//最后把新节点插入尾端
new = create_node(value);
//插入到链表开始位置,或则插入在链表中间
if (that != NULL) {
//插入起始位置
if (this ==root) {
new->next = that;
root->next = new;
new->prev = NULL;
that->prev = new;
} else {
new->next = that;
this->next =new;
new->prev = this;
that->prev =new;
}
} else {
//在链表末尾, that指针为NULL 时 跳出for循环
if (this != root) {
this->next = new;
new->next = NULL;
new->prev = this;
root->prev = new;
} else { //链表为空
root->next = new;
new->next = NULL;
root->prev = new;
new->prev = NULL;
}
}
return 0;
}
2上面这段代码过于冗长,此处介绍两个优化代码的技巧。
2.1 下面这种情况:
例子 2.1:
if (x==3) {
y = 2;
something;//表示执行任意代码
j = 3;
}else {
y = 2;
different something;
j = 3;
}
向上面这段代码,因为x是否等于3,都会y始终等于2 ,j始终等于3。 y不会影响到x的测试结果。所以上面的代码可以提炼为下面的代码。
例子 2.2:
y = 2;
if (x==3) {
something;
}else {
different something;
}
j = 3;
如果if内的代码影响了x的测试结果,则不能把相同的提取出来,例如:
例子 2.3:
if (x==3) {
x = 5;
something;
}else {
x = 5;
different something;
}
这里把x = 5 提取出去就会影响if的测试结果。所以该代码不能再优化了。此技巧看似简单,关键的时候会发挥很大的作用,能简化的代码量。
2.2 把看似表现形式不同,但功能是一样的表达式提炼出来,例如:
例子 2.4:
int * point;
int * p;
something ;//表示执行一段代码
if (point != NULL)
p = point;
else
p = NULL;
向上面这段代码就可以直接简化为下面的代码:
例子 2.5 :
int * point;
int * p;
something ;//表示执行一段代码
p = point;
为什么可以这样呢?在2.1代码中,当point不为NULL时,p 的值为point的一份拷贝.
当point为NULL时,p的值也为NULL,也可以认为p是point的一份拷贝。这和语句
p = point;的效果是一样的。
3 运用上面2个优化技巧,可以对双向链表的插入代码(代码 1)进行优化,用技巧1优化后的代码为:
例子 3.1 :
int list_insert2(Node *root,int value)
{
Node *this;
Node *that;
Node *new;
for (this = root;(that = this->next)!=NULL;
this = that) {
if (that->value == value){
return 1;
}
if (that->value > value) {
break;
}
}
new = create_node(value);
if (that != NULL) {
//插入起始位置
new->next = that;//从if中提取出来的
that->prev = new;// 从if中提取出来的
if (this ==root) {
root->next = new;
new->prev = NULL;
} else {
this->next =new;
new->prev = this;
}
} else {
new->next = NULL;//从if中提取出来的
root->prev = new;//从if中提取出来的
if (this != root) {
this->next = new;
new->prev = this;
} else { //链表为空
root->next = new;
new->prev = NULL;
}
}
return 0;
}
3.2 用技巧2优化后的代码如下:
例子 3.2:
//存在两个优化技巧,代码提炼 ,
//把看似功能表示不同,功能相同的代码提炼出来。
int list_insert3(Node *root,int value)
{
Node *this;
Node *that;
Node *new;
for (this = root;(that = this->next)!=NULL;
this = that) {
if (that->value == value){
return 1;
}
if (that->value > value) {
break;
}
}
new = create_node(value);
//代码提炼之后还是只修改4个指针
// this->next new->next that->prev new->prev
new->next = that;
if (this ==root) {
root->next = new;
new->prev = NULL;
} else {
this->next =new;
new->prev = this;
}
if (that != NULL) {
that->prev =new;
} else {
root->prev = new;
}
return 0;
}
4 运用上面介绍的技巧,现给出双向链表的删除 查找函数(函数已经优化过)。
4.1 删除函数代码:
例子 4.1:
int list_delate(Node *root,int value)
{
Node *this ;
Node *that;
Node *old;
for (this = root;(that = this ->next) != NULL;
this = that) {
if (that ->value == value) {
break;
}
}
if (that == NULL) {
printf("waring:the value( %d) is not in the list!\n",value);
return 1;
}
old = that;
this ->next = that ->next;
if (this == root) {
that ->next->prev = NULL;
} else {
if (that ->next == NULL) {
root ->prev =this;
} else {
that ->next->prev = this;
}
}
free(old);
old == NULL;
return 0;
}
4.2 查找函数代码:
例子 4.2 :
Node *list_search(Node *root,int value)
{
Node *this ;
Node *that;
Node *old;
for (this = root;(that = this ->next) != NULL;
this = that) {
if (that ->value == value) {
break;
}
}
if (that == NULL) {
printf("waring:the value( %d) is not in the list!\n",value);
return NULL;
}
return that;
}
5 下面是对上面函数的测试验证代码:
int main(int argc,char **argv)
{
//创建头结点,头结点的prev next指针
//作为链表的根指针 和尾指针
Node *root = create_node(0);
//随即插入不同的节点
list_insert1(root, 3);
list_insert1(root, 13);
list_insert1(root, 23);
list_insert1(root, 5);
list_insert1(root, 6);
list_insert1(root, 10);
list_insert1(root, 12);
list_insert1(root, 33);
Node *current = root->prev;
//按降序方式打印出来
while (current !=NULL) {
printf("root->next->value =%d\n",current->value);
current = current->prev;
}
printf("=======================\n");
list_delate(root,10);
list_delate(root,33);
list_delate(root,12);
list_delate(root,12);
current = root->prev;
while (current !=NULL) {
printf("root->next->value =%d\n",current->value);
current = current->prev;
}
printf("=======================\n");
Node * ret = list_search(root,3);
printf("ret->value = %d\n",ret->value);
return 0;
}
6 欢迎留言讨论,本文原创,转载请注明原出处。原文地址:http://blog.youkuaiyun.com/pengqian652/article/details/13629053