栈的实现

 一、栈

        栈是一种按照先进后出的数据存储结构(LIFO),它检索元素的顺序与存储元素的顺序是相反的。所谓的先进后出是指数据元素的存储与删除操作,这意味着最后一个存储的元素将会第一个被删除。举个例子,现在要把"5,4,3,2,1"存入到“栈”中,从栈的底部到顶部分别是5,4,3,2,1,当删除时,顺序为“1,2,3,4,5”。

 

实现栈的方法有很多,可以用顺序的线性存储结构和链式的非线性存储结构。顺序存储结构如数组的方式。链式存储结构,顾名思义,是采用链表的存储方式。采用链表的方式来实现栈不仅操作简单,而且可以使栈具有多态的特性。这是因为除了栈本身的一些操作外,它毕竟本身就是一种链表,它具有与链表的相同属性。因此还可以使用链表的一些操作。所以本文采用链表的方式来实现栈。

 

链表的实现如下,可参看我的其他文章。

typedef struct Node_  
{  
void *data;  
struct Node_ *next;  
}Node;  


/* define a structure for linked list */  
typedef struct List_  
{  
int size;  
void (*match)(const void *key1, const void *key2);  
void (*destroy)(void *data);  
Node *head;  
Node *tail;  
}List;  


/* define public interface */  
void list_init(List *list, void(*destroy)(void *data));  
void list_destroy(List *list);  
int list_insert_next(List *list, Node *newNode, const void *data);  
int list_remove_next(List *list, Node *newNode, void **data);  


#define list_size(list) ((list)->size)  


#define list_head(list) ((list)->head)  
#define list_tail(list) ((list)->tail)  


#define list_is_head(list, node) ((node) == (list)->head ? 1 : 0)  
#define list_is_tail(list, Node) ((Node) == (list)->tail ? 1 : 0)  


#define list_data(node) ((node)->data)  
#define list_next(node) ((node)->next)  


void list_init(List *list, void (*destroy)(void *data))  
{  
list->size = 0;  
list->destroy = destroy;  
list->head = NULL;  
list->tail = NULL;  
return;  



/* list_destroy */  
void list_destroy(List *list)  
{  
void *data; //keep the data in the element of the list  


/*remove the element */  
while( list_size(list) > 0 )   
{  
if(list_remove_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL)  
{  
list->destroy(data);  
}  
}  
memset(list, 0, sizeof(list));  
return;  
}  
/* destroy */  
void destroy(void *data)  
{  
printf("in destroy\n");  
free(data);  
return;  
}  
//elment不为空时,在该结点后面插入,为空时,在头结点前面插入。
int list_insert_next(List *list, Node *element, const void *data)  
{  
/* Allocate storage */  
Node *new_element = NULL;  
new_element = (Node *)malloc(sizeof(Node));  
if( new_element == NULL )  
return -1;  


new_element->data = (void *)data;  
/* Insert the element into the list */  
if( element == NULL ) //from head position to insert  
{  
if( list_size(list) == 0 )  //be care to tail  
list->tail = new_element;  //如果链表为空,则让新插入的结点称为尾结点


new_element->next = list->head;  //让新插入的结点指向头结点,此例头结点是由数据的。
list->head = new_element;//如果链表为空,则会让新插入的结点称为头结点
}  
else  
{  
if( element->next == NULL ) //be care to tail  
list->tail = new_element;  //如果指定的结点末尾为空,说明是尾结点,记得要更新尾结点


new_element->next = element->next;  
element->next = new_element;  
}  
/*Adjust size */  
list->size++;  
return 0;  



//删除指定结点的下一结点,如果指定结点为空,则从头结点开始删除,如果指定结点的下一结点为空,则不用删除
int list_remove_next(List *list, Node *element, void **data)  
{  
Node *old_element;  


//if the list is empty  
if( list_size(list) == 0 )  
return -1;  


/* Remove the element from the list */  
if( element == NULL ) //from head to remove  
{  
*data = list->head->data; //keep the data.  
old_element = list->head;  //取出要删除的结点,后面要释放它的空间
list->head = list->head->next;  


if( list_size(list) == 1 )  //be care to the tail ,大小为1,说明删除的是尾结点,记得更新尾结点。 
list->tail = NULL;  
}  
else  
{  
//if the element to be removed is NULL  
if( element->next == NULL )  
return -1;  


*data = element->next->data;  
old_element = element->next;  
element->next = element->next->next;  


if( element->next == NULL ) //be care to the tail  
list->tail = element;  
}  


//free the memory  
free(old_element);  


list->size--;  


return 0;  
}  
typedef List  Stack;
#define stack_init list_init 
#define stack_destroy list_destroy
//
int stack_push(Stack *stack, const void *data);
int stack_pop(Stack *stack, void **data);
#define stack_peek(stack) ((stack)->head == NULL ? NULL : (stack)->head->data)
#define stack_size list_size  


/* stack_push */  
int stack_push(Stack *stack, const void *data)  
{  
/* push the data onto the stack */  
return list_insert_next(stack, NULL, data);
}  


/* stack_pop */  
int stack_pop(Stack *stack, void **data)  
{  
/* pop the data off the stack */  
return list_remove_next(stack, NULL, data);  
}  


/* main */  
int main(int argc, char **argv)  
{  
Stack stack;  
int *int_ptr = NULL;  
int ret = 0;  
int i;  


stack_init(&stack, destroy);  


for(i = 0; i < 5; i++ )  
{  
int_ptr = (int *)malloc(sizeof(int));  
if( int_ptr == NULL )  
return -1;  


*int_ptr = i;  
printf("push the data: %d\n",i);  
ret = stack_push(&stack, (void *)int_ptr);  
if( ret != 0 )  
return -1;  
}  


printf("size of the stack is : %d\n", stack_size(&stack));  


//pop the data from top to the bottom  


for(i = stack_size(&stack); i > 0; i-- )  
{  
int_ptr = NULL;  
stack_pop(&stack, (void **)&int_ptr);  
printf("i = %d, pop the data = %d\n",i,*int_ptr);  
free(int_ptr);  
}  


printf("after pop size of the stack is :%d\n", stack_size(&stack));  
return 0;  
}  

 

奇妙之二进制 CSDN认证博客专家 嵌入式优质创作者
专注于Linux C/C++、嵌入式Linux开发,偶尔谈谈人生,目前致力于完成大约500篇的linux C/C++开发知识体系库,所有的文章都会一直保持更新(优化内容、排版),想学习的可以订阅我的专栏,也可以关注二进制人生公众号。
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:白松林 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值