双向链表
正向和反向遍历
- 双向链表
- 增加正向和反向的遍历
需要注意的是,由于遍历的过程是一个指针记录了当前节点的位置,因此在遍历过程中,不允许有改变链表结构的操作(比如增加,删除,插入节点)
头文件
#ifndef __03_LINK__H
#define __03_LINK__H
typedef struct node {
int val;
struct node * p_next;
struct node * p_prev;
} node_t;
typedef struct {
node_t head;
node_t tail;
node_t * p_cur;// remember last time operation node
} link_t;
void link_init(link_t * p_link);
void link_deinit(link_t *p_link);
int link_empty(const link_t *p_link);
int link_size(const link_t *p_link);
int link_append(link_t *p_link, int val);
int link_add_head(link_t *p_link, int val);
int link_insert(link_t *p_link, int val, int pos);
int link_insert_order(link_t *p_link, int val);
int link_remove_tail(link_t *p_link);
int link_remove_head(link_t *p_link);
int link_remove(link_t *p_link, int val);
int link_get_head(const link_t * p_link, int *p_val);
int link_get_tail(const link_t *p_link, int *p_val);
int link_get(const link_t *p_link, int *p_val, int pos);
void link_begin(link_t *);
int link_next(link_t *, int *);
void link_rbegin(link_t *);
int link_prev(link_t *, int *);
#endif
c文件
#include<stdio.h>
#include<stdlib.h>
#include"04_link.h"
void link_init(link_t * p_link)
{
p_link->head.p_next = &p_link->tail;
p_link->tail.p_prev = &p_link->head;
p_link->tail.p_next = NULL;
p_link->head.p_prev = NULL;
p_link->p_cur = NULL;
}
void link_deinit(link_t *p_link)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL;
p_link->p_cur = NULL;
while( p_link->head.p_next != &p_link->tail)
{
p_first = &p_link->head;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_last;
p_last->p_prev = p_first;
free(p_mid);
p_mid = NULL;
}
}
int link_empty(const link_t *p_link)
{
return p_link->head.p_next == &p_link->tail;
}
int link_size(const link_t *p_link)
{
const node_t *p_first = NULL, *p_mid = NULL, * p_last = NULL;
const node_t *p_tmp = NULL;
int count = 0;
for(p_tmp = &p_link->head; p_tmp != &p_link->tail; p_tmp = p_tmp->p_next )
{
p_first = p_tmp;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if (p_mid != &p_link->tail)
{
count++;
}
}
return count;
}
int link_append(link_t *p_link, int val)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_node = NULL, *p_tmp = NULL;
p_link->p_cur = NULL;
p_node = (node_t *)malloc(sizeof(node_t));
if(!p_node)
return 0;
p_node->val = val;
p_node->p_next = NULL;
p_node->p_prev = NULL;
p_first = p_link->tail.p_prev;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_node;
p_node->p_next = p_mid;
p_node->p_prev = p_first;
p_mid->p_prev = p_node;
return 1;
}
int link_add_head(link_t *p_link, int val)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp = NULL;
p_link->p_cur = NULL;
node_t * p_node = (node_t *)malloc(sizeof(node_t));
if(!p_node)
return 0;
p_node->val = val;
p_node->p_next = NULL;
p_node->p_prev = NULL;
p_first = &p_link->head;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_node;
p_node->p_next = p_mid;
p_node->p_prev = p_first;
p_mid->p_prev = p_node;
return 1;
}
int link_insert(link_t *p_link, int val, int pos)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp =NULL;
p_link->p_cur = NULL;
node_t *p_node = (node_t *)malloc(sizeof(node_t));
int cnt = 0;
if(!p_node)
return 0;
p_node->val = val;
p_node->p_next = NULL;
p_node->p_prev = NULL;
for(p_tmp = &p_link->head; p_tmp != &p_link->tail; p_tmp = p_tmp->p_next)
{
p_first = p_tmp;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if(cnt >= pos)
{
p_first->p_next = p_node;
p_node->p_next = p_mid;
p_node->p_prev = p_first;
p_mid->p_prev = p_node;
break;
}
cnt++;
}
return 1;
}
int link_insert_order(link_t *p_link, int val)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp =NULL;
node_t *p_node = (node_t *)malloc(sizeof(node_t));
p_link->p_cur = NULL;
if(!p_node)
return 0;
p_node->val = val;
p_node->p_next = NULL;
p_node->p_prev = NULL;
for(p_tmp = &p_link->head; p_tmp != &p_link->tail; p_tmp = p_tmp->p_next)
{
p_first = p_tmp;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if(p_mid->val > p_node->val || p_mid == &p_link->tail)
{
p_first->p_next = p_node;
p_node->p_next = p_mid;
p_node->p_prev = p_first;
p_mid->p_prev = p_node;
break;
}
}
return 1;
}
int link_remove_tail(link_t *p_link)
{
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL;
p_last = &p_link->tail;
p_link->p_cur = NULL;
p_mid = p_last->p_prev;
p_first = p_mid->p_prev;
if( p_mid != &p_link->head)
{
p_first->p_next = p_last;
p_last->p_prev = p_first;
free(p_mid);
p_mid = NULL;
return 1;
}
return 0;
}
int link_remove_head(link_t *p_link)
{
if(link_empty(p_link))
return 0;
p_link->p_cur = NULL;
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp =NULL;
p_first = &p_link->head;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_last;
p_last->p_prev = p_first;
free(p_mid);
p_mid = NULL;
return 1;
}
int link_remove(link_t *p_link, int val)
{
if(link_empty(p_link))
return 0;
p_link->p_cur = NULL;
node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp =NULL;
for(p_tmp = &p_link->head; p_tmp != &p_link->tail; p_tmp = p_tmp->p_next)
{
p_first = p_tmp;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if(p_mid->val == val && p_mid != &p_link->tail)
{
p_first->p_next = p_last;
p_last->p_prev = p_first;
free(p_mid);
p_mid =NULL;
return 1;
}
}
return 0;
}
int link_get_head(const link_t * p_link, int *p_val)
{
if(link_empty(p_link))
return 0;
const node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL;
p_first = &p_link->head;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if (p_mid != &p_link->tail)
{
*p_val = p_mid->val;
return 1;
}
return 0;
}
int link_get_tail(const link_t *p_link, int *p_val)
{
const node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL;
p_last = &p_link->tail;
p_mid = p_last->p_prev;
p_first = p_mid->p_prev;
if( p_mid != &p_link->head)
{
*p_val = p_mid->val;
return 1;
}
return 0;
}
int link_get(const link_t *p_link, int *p_val, int pos)
{
const node_t *p_first = NULL, *p_mid = NULL, *p_last = NULL, *p_tmp =NULL;
int cnt = 0;
for(p_tmp = &p_link->head; p_tmp != &p_link->tail; p_tmp = p_tmp->p_next)
{
p_first = p_tmp;
p_mid = p_first->p_next;
p_last = p_mid->p_next;
if(cnt == pos && p_mid != &p_link->tail)
{
*p_val = p_mid->val;
return 1;
}
cnt++;
}
return 0;
}
void link_begin(link_t * p_link) // 正向遍历初始化
{
p_link->p_cur = &p_link->head;
}
int link_next(link_t *p_link, int *p_val) // 正向遍历函数
{
if(p_link->p_cur == NULL) // link not begin traversal
return 0;
p_link->p_cur = p_link->p_cur->p_next;
if (p_link->p_cur == &p_link->tail)
{
p_link->p_cur = NULL;
return 0;
}
else {
*p_val = p_link->p_cur->val;
return 1;
}
}
void link_rbegin(link_t * p_link) // 反向遍历初始化
{
p_link->p_cur = &p_link->tail;
}
int link_prev(link_t *p_link, int *p_val) // 反向遍历函数
{
if (p_link->p_cur == NULL)
return 0;
p_link->p_cur = p_link->p_cur->p_prev;
if (p_link->p_cur == &p_link->head)
{
p_link->p_cur = NULL;
return 0;
}
else
{
*p_val = p_link->p_cur->val;
return 1;
}
}
main 函数
#include<stdio.h>
#include"04_link.h"
int main()
{
link_t lnk = {0};
int num = 0, size = 0, val = 0, tmp = 0;
link_init(&lnk);
link_append(&lnk, 10);
link_append(&lnk, 20);
link_append(&lnk, 30);
link_append(&lnk, 40);
link_append(&lnk, 50);
link_append(&lnk, 60);
link_append(&lnk, 340);
link_append(&lnk, 230);
link_append(&lnk, 123);
link_append(&lnk, 312);
link_insert_order(&lnk,0);
link_insert_order(&lnk,1000);
link_insert_order(&lnk,53);
link_remove_tail(&lnk);
link_remove_head(&lnk);
link_remove(&lnk,123);
size = link_size(&lnk);
for(num = 0; num <= size; num ++)
{
if (link_get(&lnk, &val, num))
printf("%d ",val);
}
printf("\n");
if (link_get_head(&lnk, &val))
printf("the link head is %d \n",val);
if (link_get_tail(&lnk, &val))
printf("the link tail is %d \n",val);
link_begin(&lnk);
while (1)
{
if (!link_next(&lnk, &val))
break;
printf("%d ",val);
}
printf("\n");
link_rbegin(&lnk);
while (1)
{
if (!link_prev(&lnk, &val))
break;
printf("%d ",val);
}
printf("\n");
link_deinit(&lnk);
}
运行结果
10 20 30 40 50 53 60 340 230 312
the link head is 10
the link tail is 312
10 20 30 40 50 53 60 340 230 312
312 230 340 60 53 50 40 30 20 10