2020-10-31

双向链表

正向和反向遍历

  1. 双向链表
  2. 增加正向和反向的遍历
    需要注意的是,由于遍历的过程是一个指针记录了当前节点的位置,因此在遍历过程中,不允许有改变链表结构的操作(比如增加,删除,插入节点)

头文件

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值