双向链表就是两个指针,一个指向前,另一个指向后。因此,我们可以从任何一个节点遍历。
这次也是要实现一个有序双向链表。
思路:
我们把一个节点插入链表时候,有四种情况:
1、 新值可能插在链表中间
2、 新值可能插在链表结束位置
3、 新值可能插在链表开头
4、 新值插入的位置,既是开头就是结束位置。
算法也是比较简单:插入一个值,先拆链后上链。
下面就是代码展示。
//最开始写的代码
int LisrInsert3(struct node_t *psthead,struct node_t *pstnew)
{
struct node_t *pos = NULL;
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return -1;
}
if(NULL == pstnew)
{
printf("pstnew is null,please check pstnew\n");
}
for(pos = psthead->next; pos != psthead; pos = pos->next)
{
if(pstnew->data > pos->data)
break;
}
//插入开始的位置
if(pos->next == psthead)
{
pstnew->next = psthead->next;
pstnew->prev = psthead;
psthead->next->prev = pstnew;
psthead->next = pstnew;
}
else
{
if(pos->next == psthead) //插入尾部
{
pos->next = pstnew;
pstnew->prev = pos;
pstnew->next = psthead;
psthead->prev = pstnew;
}
else//不是尾部也不是开头
{
pos->next->prev = pstnew;
pstnew->next = pos->next;
pos->next = pstnew;
pstnew->prev = pos;
}
}
}
第一次简化的代码:
int LisrInsert(struct node_t *psthead,struct node_t *pstnew)
{
struct node_t *pos = NULL;
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return -1;
}
if(NULL == pstnew)
{
printf("pstnew is null,please check pstnew\n");
}
for(pos = psthead; pos->next != psthead; pos = pos->next)
{
if(pstnew->data > pos->next->data)
break;
}
//插入开始的位置
if(pos == psthead)
{
pstnew->next = psthead->next;
pstnew->prev = psthead;
psthead->next->prev = pstnew;
psthead->next = pstnew;
}
else
{
if(pos->next == psthead) //插入尾部
{
pos->next = pstnew;
pstnew->prev = pos;
pstnew->next = psthead;
psthead->prev = pstnew;
}
else//不是尾部也不是开头
{
pos->next->prev = pstnew;
pstnew->next = pos->next;
pos->next = pstnew;
pstnew->prev = pos;
}
}
}
第二次优化的代码:
//代码简化
int LisrInsert1(struct node_t *psthead,struct node_t *pstnew)
{
struct node_t *pos = NULL;
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return -1;
}
if(NULL == pstnew)
{
printf("pstnew is null,please check pstnew\n");
}
for(pos = psthead; pos->next != psthead; pos = pos->next)
{
if(pstnew->data > pos->next->data)
break;
}
//插入开始的位置
if(pos == psthead)
{
pstnew->next = psthead->next;
pstnew->prev = psthead;
psthead->next->prev = pstnew;
psthead->next = pstnew;
}
else
{
pstnew->prev = pos;
pstnew->next = pos->next;
pos->next->prev = pstnew;
pos->next = pstnew;
}
}
最终版本的代码:
//代码简化2
int LisrInsert2(struct node_t *psthead,struct node_t *pstnew)
{
struct node_t *pos = NULL;
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return -1;
}
if(NULL == pstnew)
{
printf("pstnew is null,please check pstnew\n");
}
for(pos = psthead; pos->next != psthead; pos = pos->next)
{
if(pstnew->data > pos->next->data)
break;
}
pstnew->prev = pos;
pstnew->next = pos->next;
pos->next->prev = pstnew;
pos->next = pstnew;
}
其它代码:
//双链表插入的实现
int ListAddAfter(struct node_t *psthead,struct node_t *pstnew)
{
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return -1;
}
if(NULL == pstnew)
{
printf("pstnew is null,please check pstnew\n");
}
psthead->prev->next = pstnew;
pstnew->prev = psthead->prev;
pstnew->next = psthead;
psthead->prev = pstnew;
}
void display(struct node_t *psthead)
{
struct node_t *pos = NULL;
for(pos = psthead->next; pos != psthead; pos = pos->next)
{
printf("%d ",pos->data);
}
printf("\n");
}
void freeDoubleList(struct node_t *psthead)
{
struct node_t *pos = NULL;
if(NULL == psthead)
{
printf("psthead is null,please chech head\n");
return;
}
for(pos =psthead->next;pos != psthead; pos = pos->next )
{
free(pos);
}
printf("free node finish\n");
}
主函数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义一个双链表节点
struct node_t{
int data;
struct node_t *next;
struct node_t *prev;
};
//定义一个头节点并初始化
struct node_t head = {0,&head,&head};
int ListAddAfter(struct node_t *psthead,struct node_t *pstnew);
void freeDoubleList(struct node_t *psthead);
void display(struct node_t *psthead);
int LisrInsert(struct node_t *psthead,struct node_t *pstnew);
int LisrInsert1(struct node_t *psthead,struct node_t *pstnew);
int LisrInsert2(struct node_t *psthead,struct node_t *pstnew);
int LisrInsert3(struct node_t *psthead,struct node_t *pstnew);
int main()
{
struct node_t *node = NULL;
int i = 0;
int j;
for(i = 0; i < 10; i++)
{
j = i*2;
node = (struct node_t *)malloc(sizeof(struct node_t));
node->data = j;
// ListAddAfter(&head,node);
LisrInsert3(&head,node);
}
#if 1
//验证插入中间
node = (struct node_t *)malloc(sizeof(struct node_t));
node->data = 5;
LisrInsert3(&head,node);
//插入开头
node = (struct node_t *)malloc(sizeof(struct node_t));
node->data = 20;
LisrInsert3(&head,node);
//插入尾部
node = (struct node_t *)malloc(sizeof(struct node_t));
node->data = -1;
LisrInsert3(&head,node);
#endif
display(&head);
freeDoubleList(&head);
return 0;
}
总结:一开始,并不能写出体积最小的代码。因为对双链表的不同操作没有总结出共性,后来经过不断总结,发现了规律,才得出最终的版本。因此能写出体积小,效率更高的程序员,很佩服。