您的位置:首页 > 编程语言

双向链表基本操作及代码优化技巧

2013-10-30 15:59 429 查看
以下是本人对双向链表的相关操作及相应的代码优化学习笔记

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 欢迎留言讨论,本文原创,转载请注明原出处。原文地址:/article/10098737.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: