c语言之————有头循环双链表(公用par)

本文介绍了一种有头循环双链表的数据结构实现,包括初始化、插入、获取、删除等基本操作,并通过一个简单的C语言示例展示了其使用方法。

本例为公用的有头循环双链表

dlist.h

/*
 *dlist.h
 *描述:
 *		有头循环双表
 *Data:
 *		2014-07-21
 */

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node_info
{
	struct node_info *prev;
	struct node_info *next;
	char par[];  			/*0长数组,不占空间*/
};

struct list_info
{
	struct node_info head;
	/*
	 * 头插
	 */
	void (*add)(struct list_info *,size_t data_size,const void *data_entry);
	/*
	 * 尾插
	 */
	void (*add_tail)(struct list_info *,size_t data_size,const void *data_entry);
	/*
	 * 得到第一个数据
	 */
	void (*get)(struct list_info *,size_t data_size,void *data_entry);
	/*
	 * 获得最后一个数据
	 */
	void (*get_tail)(struct list_info *,size_t data_size, void *data_entry);
	/*
	 * 删除节点
	 */
	void (*del)(struct list_info *,struct node_info *);
	/*
	 * 判断节点是否为空
	 */
	int (*isempty)(struct list_info *);
};

void list_init(struct list_info*);
void list_destroy(struct list_info*);

#define PAR(node,type) ((type*)node->par)

#define list_for_each(info, cur) \
	for (cur = (info)->head.next; \
		(cur) != &(info)->head; \
		cur = (cur)->next)

#define list_for_each_safe(info, cur, tmp) \
	for (cur = (info)->head.next, tmp = (cur)->next; \
		(cur) != &(info)->head; \
		cur = tmp, tmp = (tmp)->next)


dlist.c

/*
 *dlist.c
 *
 */

#include "dlist.h"

static void list_add(struct list_info *info,size_t data_size,const void *data_entry)
{
	struct node_info *new_node = (struct node_info *)malloc(sizeof(struct node_info) + data_size);

	memcpy(new_node->par,data_entry,data_size);

	new_node->prev = &info->head;
	new_node->next = info->head.next;
	info->head.next = new_node;
	new_node->next->prev = new_node;//info->head.next->prev = new_node;
}

static void list_add_tail(struct list_info *info,size_t data_size,const void *data_entry)
{
	struct node_info *new_node = (struct node_info *)malloc(sizeof(struct node_info) + data_size);

	memcpy(new_node->par,data_entry,data_size);

	new_node->prev = info->head.prev;
	new_node->next = &info->head;
	info->head.prev->next = new_node;
	info->head.prev = new_node;		//new_node->prev->next = new_node;
}

static void list_get(struct list_info *info,size_t data_size,void *data_entry)
{
	memcpy(data_entry, info->head.next->par, data_size);
}

static void list_get_tail(struct list_info *info,size_t data_size,void *data_entry)
{
	memcpy(data_entry, info->head.prev->par, data_size);
}

static void list_del(struct list_info *info,struct node_info *node)
{
	node->prev->next = node->next;
	node->next->prev = node->prev;

	node->next = node;
	node->prev = node;

	free(node);
}

static int list_isempty(struct list_info *info)
{
//	return info->head.prev  == &info->head;
	return info->head.next == &info->head;
}

void list_init(struct list_info *info)
{
	info->head.prev = &info->head;
	info->head.next = &info->head;
	info->add = list_add;
	info->add_tail = list_add_tail;
	info->get = list_get;
	info->get_tail = list_get_tail;
	info->del = list_del;
	info->isempty = list_isempty;
}

void list_destroy(struct list_info *info)
{
	struct node_info *cur = NULL;
	struct node_info *tmp = NULL;
	list_for_each_safe(info, cur, tmp)
	{
		info->del(info, cur);
	}
}

test.c

/*
 * test.c
 *
 */

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

struct data_info {
	const char *name;
	size_t age;
};

int main()
{
	struct data_info s[] = {
		{"jack", 20},
		[1] = {
			.name = "marry",
			.age = 22,
		},
		[2] = {
			"peter",
			21,
		},
	};

	struct list_info list;
	list_init(&list);

	size_t i = 0;
	for (i = 0; i < sizeof(s) / sizeof(struct data_info); ++i) {
		list.add_tail(&list, sizeof(struct data_info), s + i);
	}

	if (!list.isempty(&list)) {
		printf("list is not empty\n");
	} else {
		printf("list is empty\n");
	}

	struct node_info *cur = NULL;
	struct node_info *tmp = NULL;
	list_for_each(&list, cur) {
		printf("%s: %ld\n", PAR(cur, struct data_info)->name, PAR(cur, struct data_info)->age);
	}

	printf("==============\n");

	list_for_each_safe(&list, cur, tmp) {
		if (PAR(cur, struct data_info)->age == 22) {
			list.del(&list, cur);
		}
	}

	if (!list.isempty(&list)) {
		struct data_info data;
		list.get_tail(&list, sizeof(struct data_info), &data);
		printf("%s: %ld\n", data.name, data.age);
		printf("==============\n");
	}

	list_for_each(&list, cur) {
		printf("%s: %ld\n", PAR(cur, struct data_info)->name, PAR(cur, struct data_info)->age);
	}

	list_destroy(&list);

	if (!list.isempty(&list)) {
		printf("list is not empty\n");
	} else {
		printf("list is empty\n");
	}

	return 0;
}

Makefile

all:test

test:test.o dlist.o
	gcc -o $@ $^
	
test.o:test.c
	gcc -c test.c
	
dlist.o:dlist.c
	gcc -c dlist.c
	
	
clean:
	rm *.o test

运行结果:

list is not empty
jack: 20
marry: 22
peter: 21
==============
peter: 21
==============
jack: 20
peter: 21
list is empty



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值