C语言方式实现双向链表

太久不看数据结构都忘记了,所以现在复习下双向链表,代码如下:

list.h

/*双向链表*/
#ifndef _LIST_H
#define _LIST_H
#include <sys/types.h>
#include <stdbool.h>
/*节点*/
typedef struct ListNode
{
		int data;				//数据
		struct ListNode* prev;	//前指针
		struct ListNode* next;	//后指针
}LIST_NODE;
/*链表*/
typedef struct List
{
	LIST_NODE* head;	//头指针
	LIST_NODE* tail;	//尾指针
	LIST_NODE* frwd;	//正向迭代指针
	LIST_NODE* bkwd;	//反向迭代指针
}LIST;

/*初始化空链表*/
void list_init(LIST* list);
/*释放剩余节点并恢复初始状态*/
void list_deinit(LIST* list);
/*判断是否为空*/
bool list_empty(LIST* list);
/*追加*/
void list_append(LIST* list,int data);
/*前插*/
bool list_insert(LIST* list,size_t pos,int data);
/*随机访问,即可读,又可写,所以返回为指针*/
int* list_at(LIST* list,size_t pos);
/*删除*/
bool list_erase(LIST* list,size_t pos);
/*删除所有的匹配数据*/
void list_remove(LIST* list,int data);
/*清空*/
void list_clear(LIST* list);
/*大小*/
size_t list_size(LIST* list);
/*开始正向迭代*/
int* list_begin(LIST* list);
/*向后正向迭代*/
int* list_next(LIST* list);
/*向前正向迭代*/
int* list_prev(LIST* list);
/*获取正向迭代的值*/
int* list_current(LIST* list);
/*判断正向迭代是否终止*/
bool list_end(LIST* list);
/*开始反向迭代*/
void list_rbegin(LIST* list);
/*向后反向迭代*/
int* list_rnext(LIST* list);
/*向前反向迭代*/
int* list_rprev(LIST* list);
/*获取反向迭代的值*/
int* list_rcurrent(LIST* list);
/*判断反向迭代是否终止*/
bool list_rend(LIST* list);
#endif

list.c

 

#include <stdlib.h>
#include "list.h"
/*创建节点*/
static LIST_NODE* create_node(int data,LIST_NODE* prev,LIST_NODE* next)
{
	LIST_NODE* node = malloc(sizeof(LIST_NODE));
	node->data = data;
	node->prev = prev;
	node->next = next;
	return node;
}
/*销毁节点,返回值后节点地址,参数输出前节点地址*/
static LIST_NODE* destroy_node(LIST_NODE* node,LIST_NODE** prev)
{
	LIST_NODE* next = node->next;
	if(prev)
		*prev = node->prev;
	free(node);
	return next;	
}
/*初始化空链表*/
void list_init(LIST* list)
{
	list->head = NULL;
	list->tail = NULL;
}
/*释放剩余节点并恢复初始状态*/
void list_deinit(LIST* list)
{
	while(list->head)
		list->head = destroy_node(list->head,NULL);
	list->tail = NULL;
}
/*判断是否为空*/
bool list_empty(LIST* list)
{
	return !list->head && !list->tail;
}
/*追加*/
void list_append(LIST* list,int data)
{
	list->tail = create_node(data,list->tail,NULL);
	if(list->tail->prev)
		list->tail->prev->next = list->tail;
	else
		list->head = list->tail;
}
/*前插*/
bool list_insert(LIST* list,size_t pos,int data)
{
	LIST_NODE* find = NULL;
	for(find = list->head;find;find = find->next)
		if(!pos--)
		{
			LIST_NODE* node = create_node(data,find->prev,find);
			if(node->prev)
				node->prev->next = node;
			else
				list->head = node;
			node->next->prev = node;
			return  true;
		}
	return false;
}
/*随机访问,即可读,又可写,所以返回为指针*/
int* list_at(LIST* list,size_t pos)
{
	LIST_NODE* find = NULL;
	for(find = list->head;find;find = find->next)
		if(!pos--)
			return &find->data;
	return NULL;
}
/*删除*/
bool list_erase(LIST* list,size_t pos)
{
	LIST_NODE* find = NULL;
	for(find = list->head;find;find = find->next)
	{
		if(!pos--)
		{
			LIST_NODE* prev = NULL;
			LIST_NODE* next = destroy_node(find,&prev);
			if(prev)
				prev->next = next;
			else
				list->head = next;
			if(next)
				next->prev = prev;
			else
				list->tail = prev;
			return true;
		}
	}
	return false;
}
/*删除所有的匹配数据*/
void list_remove(LIST* list,int data)
{
	LIST_NODE* find = NULL,*next = NULL;
	for(find = list->head;find;find = next)
	{
		next = find->next;				//防止链表迭代失效,如果上述使用find = find->next
		if(find->data == data)			//,find如果删除,导致find->next失效,就像STL容器一样
		{
			LIST_NODE* prev = NULL;
			LIST_NODE* next = destroy_node(find,&prev);
			if(prev)
				prev->next = next;
			else
				list->head = next;
			if(next)
				next->prev = prev;
			else
				list->tail = prev;
		}
	}
}
/*清空*/
void list_clear(LIST* list)
{
	list_deinit(list);
}
/*大小*/
size_t list_size(LIST* list)
{
	size_t size = 0;
	LIST_NODE* node = NULL;
	for(node = list->head;node;node = node->next)
			++size;
	return size;
}
/*开始正向迭代*/
int* list_begin(LIST* list)
{
	list->frwd = list->head;
}
/*向后正向迭代*/
int* list_next(LIST* list)
{
	int* data = &list->frwd->data;
	list->frwd = list->frwd->next;
	return data;
}
/*向前正向迭代*/
int* list_prev(LIST* list)
{
	int* data = &list->frwd->data;
	list->frwd = list->frwd->prev;
	return data;
}
/*获取正向迭代的值*/
int* list_current(LIST* list)
{
	return &list->frwd->data;
}
/*判断正向迭代是否终止*/
bool list_end(LIST* list)
{
	return !list->frwd;
}
/*开始反向迭代*/
void list_rbegin(LIST* list)
{
	list->bkwd = list->tail;
}
/*向后反向迭代*/
int* list_rnext(LIST* list)
{
	int* data = &list->bkwd->data;
	list->bkwd = list->bkwd->prev;
	return data;
}
/*向前反向迭代*/
int* list_rprev(LIST* list)
{
	int* data = &list->bkwd->data;
	list->bkwd = list->bkwd->next;
	return data;
}
/*获取反向迭代的值*/
int* list_rcurrent(LIST* list)
{
	return &list->bkwd->data;
}
/*判断反向迭代是否终止*/
bool list_rend(LIST* list)
{
	return !list->bkwd;
}

list_test.c

#include <stdio.h>
#include "list.h"

/*测试用例*/
void print(LIST* list)
{
	//打印复杂度为平方,循环内还有循环
	/*size_t pos,size = list_size(list);
	for(pos = 0; pos < size; ++pos)
			printf("%d ",*list_at(list,pos));
	printf("\n");*/
	
	//正打
	for(list_begin(list);!list_end(list);list_next(list))
			printf("%d ",*list_current(list));
		printf("\n");
		
	/*反打*/
	/*for(list_rbegin(list); !list_rend(list);list_rnext(list))
		printf("%d ",*list_rcurrent(list));
	printf("\n");*/
}

void square(LIST* list)
{
	for(list_begin(list);!list_end(list);list_next(list))
			*list_current(list) *= *list_current(list);
}

void test1(void)
{
	LIST list;
	list_init(&list);
	list_append(&list,10);
	list_append(&list,30);
	list_append(&list,50);
	print(&list);	/* 10 20 50*/
	list_insert(&list,1,20);
	list_insert(&list,3,40);
	print(&list);	/* 10 20 30 40 50*/
	list_erase(&list,2);
	list_erase(&list,3);
	print(&list);	/*10 20 40*/
	list_append(&list,20);
	list_insert(&list,0,20);
	print(&list);	/*20 10 20 40 20*/
	list_remove(&list,20);
	print(&list);	/* 10 40*/
	square(&list);
	print(&list);	/*100 1600*/
	list_deinit(&list);
	
}

int main(void)
{
	test1();
	return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值