双向循环链表

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//双向循环链表
#define DEBUG_PRINTF

typedef int datatype;
typedef enum{
	false = 0,
	true = 1
}bool;

//设计节点
typedef struct dlist{
	datatype  id;
	struct dlist *prev;	
	struct dlist *next;
}L;
 
/*判断链表是否为空
true is empty
false is't empty
*/
bool list_is_empty(L * p)
{
	if(p->next == p->prev && p->next == p)
		return true;
	return false;
}

/*初始化带有头节点的双向循环链表
success return p 
fail    return null
*/
L *init_dlist(void)
{
	L * p = malloc(sizeof(L)); //分配空间

	if(p == NULL)
	{
		#ifdef DEBUG_PRINTF
		printf("malloc error\n");
		#endif
		return NULL;
	}
	memset(p,0,sizeof(L));
	p->next = p->prev = p;//注意是指向头节点自己
	return p;
}


/*创建一个节点 
success return p 
fail    return null
*/
L *create_dlist(datatype data)
{
	L * p = malloc(sizeof(L)); //分配空间

	if(p == NULL)
	{
		#ifdef DEBUG_PRINTF
		printf("malloc error\n");
		#endif
		return NULL;
	}
	memset(p,0,sizeof(L));
	p->id = data;
	p->next = p->prev = NULL;//注意是指向头节点自己
	return p;
}

//在链表m节点后插入一个节点new
bool node_insert_next(L *m,L *new)
{
	if(m == NULL || new == NULL)
		return false;

	new->prev = m;
	new->next = m->next;//先处理new前后指针
	
	m->next = new;
	new->next->prev = new;
	
	return true;
}

//在链表m节点前插入一个节点new
bool node_insert_prev(L *m,L *new)
{
	if(m == NULL || new == NULL)
		return false;
	
	new->prev = m->prev;
	new->next = m;//先处理new前后指针
	
	m->prev->next = new;
	//new->prev->next = new;
	m->prev = new;
	
	return true;
}

//直接在链表最后位置插入一个节点new
//pH是头节点
bool tail_insert(L *pH,L *new)
{
	if(pH == NULL || new == NULL)
		return false;
		
	//获取当前位置
	L * p = pH->next;
	while(p != pH)
	{  //当前位置下一个节点不为空则移动到下一个节点
		p = p->next;
	}
	//循环跳出,则p == pH
	return node_insert_prev(p,new);//插在head的前面就是插在最后
}



//删除一个节点
bool delete_node(L *delete,int is_free)
{
	if(delete == NULL)
		return false;
	
	delete->prev->next = delete->next;
	delete->next->prev = delete->prev;

	delete->next = NULL;
	delete->prev = NULL;
	if(is_free) //如果要释放
	{
		free(delete);
		delete = NULL;
	}
	return true;
}

/*
移动一个节点m
1.删除一个节点(不释放)
2.插入一个节点
*/
bool move_node_prev(L * m,L * a)
{
	
	//1.删除m节点(不释放)
	if(delete_node(m,0) == false)
		return false;	
   //在链表m节点前插入一个节点new
    return node_insert_prev(a,m);
}

/*
移动一个节点m
1.删除一个节点(不释放)
2.插入一个节点
*/
bool move_node_next(L * m,L * a)
{
	
	//1.删除m节点(不释放)
	if(delete_node(m,0) == false)
		return false;	
   //在链表m节点前插入一个节点new
    return node_insert_next(a,m);
}

/*
移动一个节点m到结尾
1.删除一个节点(不释放)
2.插入一个节点到结尾
*/
bool move_node_tail(L * m,L * pH)
{
	//1.删除m节点(不释放)
	if(delete_node(m,0) == false)
		return false;	
	return tail_insert(pH,m);
}


//根据数据查找节点
L * find_node(L * pH,datatype data)
{
	if(pH == NULL)
		return NULL; 
	if(list_is_empty(pH) == true)
		return NULL; //空就直接返回NULL
	L * p;
	for(p=pH->next ; p != pH ; p=p->next)
	{
		if(data == p->id)
			break;
	}
	return p == pH ? NULL:p;//p==pH说明找不到,则返回null
}
/*从最后一个开始,从右到左依次移动到head前面*/
void revert_node(L *pH)
{
	L * p = pH->prev,*g;
	//p指向head前面也就是最后一个
	while(p !=pH)
	{
		g = p->prev;//g指向p的前面也就是倒数第二个
		move_node_tail(p,pH);
		p = g;//这时g成立最后一个赋值给p
	}
}

void show_node(L * pH)
{
	//if(list_is_empty(pH) == true)
	//	return; //空就直接返回NULL
	
	L*p = pH->next;//第一个node位置
	int i=0;
	while(p != pH)
	{
		printf("addr:%p{prev:%p id:%d next:%p}\n",p,p->prev,p->id,p->next);
		//printf("%s%d",i==0?"":" -->",p->id);
		p = p->next;
		i++;
	}
	if(p == pH)//打印头节点
	  printf("addr:%p{prev:%p id:header next:%p}\n",p,p->prev,p->next);
	printf("\n");
}

int main()
{
	int i;
	L *header = init_dlist();
	show_node(header); //1~10
	for(i=1;i<=10;i++)
	{   
		tail_insert(header,create_dlist(i));
		//node_insert_prev(header,create_dlist(i));
	}
	show_node(header); //1~10
	
	delete_node(find_node(header,5),0);
	show_node(header);//1~4 6~10
	
	node_insert_next(find_node(header,4),create_dlist(5));
	show_node(header);//1~10
	
	move_node_next(find_node(header,4),find_node(header,5));
	show_node(header);//4移到5后

	move_node_prev(find_node(header,4),find_node(header,5));
	show_node(header);//4移到5前
	
	move_node_tail(find_node(header,4),header);
	show_node(header);//4移到最后
	
	delete_node(find_node(header,4),1);
	show_node(header);//4删除并释放
	
	revert_node(header);
	show_node(header);//逆序
	printf("\n\n\n");
	
	return 0;
}

节点地址打印如下

addr:0x8470008{prev:0x8470008 id:header next:0x8470008} 头节点

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x8470048}
addr:0x8470048{prev:0x8470038 id:4 next:0x8470058}
addr:0x8470058{prev:0x8470048 id:5 next:0x8470068}
addr:0x8470068{prev:0x8470058 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018} 头节点

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x8470048}
addr:0x8470048{prev:0x8470038 id:4 next:0x8470068}
addr:0x8470068{prev:0x8470048 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018}

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x8470048}
addr:0x8470048{prev:0x8470038 id:4 next:0x84700b8}
addr:0x84700b8{prev:0x8470048 id:5 next:0x8470068}
addr:0x8470068{prev:0x84700b8 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018}

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x84700b8}
addr:0x84700b8{prev:0x8470038 id:5 next:0x8470048}
addr:0x8470048{prev:0x84700b8 id:4 next:0x8470068}
addr:0x8470068{prev:0x8470048 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018}

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x8470048}
addr:0x8470048{prev:0x8470038 id:4 next:0x84700b8}
addr:0x84700b8{prev:0x8470048 id:5 next:0x8470068}
addr:0x8470068{prev:0x84700b8 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018}

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x84700b8}
addr:0x84700b8{prev:0x8470038 id:5 next:0x8470068}
addr:0x8470068{prev:0x84700b8 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470048}
addr:0x8470048{prev:0x84700a8 id:4 next:0x8470008}
addr:0x8470008{prev:0x8470048 id:header next:0x8470018}

addr:0x8470018{prev:0x8470008 id:1 next:0x8470028}
addr:0x8470028{prev:0x8470018 id:2 next:0x8470038}
addr:0x8470038{prev:0x8470028 id:3 next:0x84700b8}
addr:0x84700b8{prev:0x8470038 id:5 next:0x8470068}
addr:0x8470068{prev:0x84700b8 id:6 next:0x8470078}
addr:0x8470078{prev:0x8470068 id:7 next:0x8470088}
addr:0x8470088{prev:0x8470078 id:8 next:0x8470098}
addr:0x8470098{prev:0x8470088 id:9 next:0x84700a8}
addr:0x84700a8{prev:0x8470098 id:10 next:0x8470008}
addr:0x8470008{prev:0x84700a8 id:header next:0x8470018}

addr:0x84700a8{prev:0x8470008 id:10 next:0x8470098}
addr:0x8470098{prev:0x84700a8 id:9 next:0x8470088}
addr:0x8470088{prev:0x8470098 id:8 next:0x8470078}
addr:0x8470078{prev:0x8470088 id:7 next:0x8470068}
addr:0x8470068{prev:0x8470078 id:6 next:0x84700b8}
addr:0x84700b8{prev:0x8470068 id:5 next:0x8470038}
addr:0x8470038{prev:0x84700b8 id:3 next:0x8470028}
addr:0x8470028{prev:0x8470038 id:2 next:0x8470018}
addr:0x8470018{prev:0x8470028 id:1 next:0x8470008}
addr:0x8470008{prev:0x8470018 id:header next:0x84700a8}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值