c语言之————有头循环双链表实现栈存储

栈的原理是先进的后出来


1、链表的实现

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);
	}
}

2、栈的实现

stack.h

/*
 * stack.h
 *
 */

#pragma once

#include "dlist.h"

struct stack_info
{
	struct list_info list;
	/*
	 * 入栈:
	 * 		通过把数据头插入链表中
	 */
	void (*push)(struct stack_info *,size_t size,const void *data_entry);

	/*
	 * 出栈:
	 * 		获得链表中的第一个数据,并把它从链表中删除
	 */
	int (*pop)(struct stack_info *,size_t size,void *data_entry);

	/*
	 * 设置栈顶指针:
	 * 			把链表中的第一个数据设置为栈顶
	 */
	int (*top)(struct stack_info *,size_t size,void *data_entry);

	/*
	 * 判断栈是否为空栈:
	 *
	 */
	int (*isempty)(struct stack_info *);
};

struct stack_info* stack_init(struct stack_info *);
void stack_destroy(struct stack_info *);

stack.c

/*
 * stack.c
 *
 */

#include "stack.h"

static void stack_push(struct stack_info *info,size_t size,const void *data_entry)
{
	info->list.add(&info->list,size,data_entry);
}

static int stack_top(struct stack_info *info,size_t size,void *data_entry)
{
	/*
	 * 栈为空就退出
	 */
	if(info->isempty(info))
	{
		return -1;
	}
	/*
	 * 如果栈不为空,就获得链表的第一个数据
	 */
		info->list.get(&info->list,size,data_entry);

		return 0;
}

static int stack_pop(struct stack_info *info,size_t size,void *data_entry)
{
	/*
	 * 如果没有栈顶数据就不能进行出栈操作,退出
	 */
	if(info->top(info,size,data_entry) < 0)
	{
		return -1;
	}
	else
	{
		info->list.del(&info->list,info->list.head.next);
		return 0;
	}
}

static int stack_isempty(struct stack_info *info)
{
	return info->list.isempty(&info->list);
}

struct stack_info *stack_init(struct stack_info *info)
{
	list_init(&info->list);
	info->push = stack_push;
	info->pop = stack_pop;
	info->isempty = stack_isempty;
	info->top = stack_top;

	return info;
}

void stack_destroy(struct stack_info *info)
{
	list_destroy(&info->list);
}

3、测试代码

test.c

/*
 * test.c
 *
 */

#include "stack.h"

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


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

	stack_init(&stack);

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

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

	struct data_info tmp;
	if(stack.top(&stack,sizeof(struct data_info),&tmp))
		printf("no top data!\n");
	else
	{
		printf("Top data is : name %s , age is %d \n",tmp.name,tmp.age);
	}

	stack_destroy(&stack);

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

	return 0;
}

4、Makfile

all:test

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

5、运行结果

stack is not empty!
Top data is : name peter , age is 21 
After destroy stack ... 
stack is empty!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
循环双向链表是一种链表结构,它可以在单链表的基础上,增加一个指向前一个结点的指针,从而实现双向遍历。循环双向链表是指尾结点的 next 指针指向头结点,头结点的 prev 指针指向尾结点,形成一个循环。 以下是循环双向链表的 C 语言实现: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *prev; struct Node *next; } Node; Node *create_node(int data) { Node *new_node = (Node *)malloc(sizeof(Node)); new_node->data = data; new_node->prev = NULL; new_node->next = NULL; return new_node; } void insert_node(Node **head, Node *new_node) { if (*head == NULL) { *head = new_node; (*head)->prev = new_node; (*head)->next = new_node; } else { Node *tail = (*head)->prev; tail->next = new_node; new_node->prev = tail; new_node->next = *head; (*head)->prev = new_node; } } void delete_node(Node **head, Node *del_node) { if (*head == NULL || del_node == NULL) { return; } if (*head == del_node) { *head = del_node->next; } if (del_node->next != NULL) { del_node->next->prev = del_node->prev; } if (del_node->prev != NULL) { del_node->prev->next = del_node->next; } free(del_node); } void print_list(Node *head) { if (head == NULL) { printf("List is empty\n"); } else { Node *current = head; do { printf("%d ", current->data); current = current->next; } while (current != head); printf("\n"); } } int main() { Node *head = NULL; Node *node1 = create_node(1); Node *node2 = create_node(2); Node *node3 = create_node(3); insert_node(&head, node1); insert_node(&head, node2); insert_node(&head, node3); print_list(head); delete_node(&head, node2); print_list(head); return 0; } ``` 在上面的代码中,我们定义了一个 Node 结构体,表示循环双向链表的结点。create_node 函数用于创建一个新结点,insert_node 函数用于将新结点插入链表,delete_node 函数用于删除指定结点,print_list 函数用于打印链表。 在 main 函数中,我们创建了三个结点,然后插入链表,打印链表,删除第二个结点,再次打印链表。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值