注:本文的主要目的是为了记录自己的学习过程,也方便与大家做交流。转载请注明来自:
http://blog.youkuaiyun.com/ab198604
一、栈
栈是一种按照先进后出的数据存储结构(LIFO),它检索元素的顺序与存储元素的顺序是相反的。所谓的先进后出是指数据元素的存储与删除操作,这意味着最后一个存储的元素将会第一个被删除。举个例子,现在要把"5,4,3,2,1"存入到“栈”中,从栈的底部到顶部分别是5,4,3,2,1,当删除时,顺序为“1,2,3,4,5”。
不说理论了,来点干货。如何实现“栈”这种数据结构呢?其实,实现栈的方法有很多,可以用顺序的线性存储结构和链式的非线性存储结构。顺序存储结构如数组的方式。链式存储结构,顾名思义,是采用链表的存储方式。采用链表的方式来实现栈不仅操作简单,而且可以使栈具有多态的特性。这是因为除了栈本身的一些操作外,它毕竟本身就是一种链表,它具有与链表的相同属性。因此还可以使用链表的一些操作。所以本文采用链表的方式来实现栈。
二、栈的结构及接口定义
由于栈是链表的另一种表现形式,所以对栈的结构定义可以在链表的基础上进行一次封装。如下所示:
/*
* filename: stack.h
* author:zhm
* date:2012-01-05
*/
#ifndef STACK_H
#define STACK_H
#include <stdlib.h>
#include "list.h"
typedef List Stack;//对List类型重新定义
对链表的结构定义及接口,在《数据结构学习之单向链表结构》已经说明,这里不再讲述,有需要的朋友可以登录这个地址访问相关的内容:
http://blog.youkuaiyun.com/ab198604/article/details/8253405
由上面的typedef List Stack语句就已经实现了栈结构的定义了。下面为栈的相关操作:
/* public interface */
#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
主要有栈的初始化,栈的销毁,压栈操作,入栈操作等。栈的初始化、销毁及栈元素大小获取等都是在原链表接口的基础上用#define语句进一步封装而成。
三、栈的接口实现细节
真正要实现的就是压栈和入栈操作了,通过调用链表的接口就能实现,看下面代码:
/*
* filename: stack.c
* author: zhm
* date: 2012-01-05
*/
#include <stdlib.h>
#include "list.h"
#include "stack.h"
/* stack_push */
int stack_push(Stack *stack, const void *data)
{
/* push the data onto the stack */
return list_ins_next(stack, NULL, data);
}
/* stack_pop */
int stack_pop(Stack *stack, void **data)
{
/* pop the data off the stack */
return list_rem_next(stack, NULL, data);
}
四、栈的应用举例
看下面代码:
/*
* filename: main.c
* author:zhm
* date: 2013-01-05
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "list.h"
#include "stack.h"
/* destroy */
void destroy(void *data)
{
printf("in destroy\n");
free(data);
return;
}
/* 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;
}
上述main()函数所实现的功能主要是将数据:0,1,2,3,4分别压入栈中,然后将其一一从栈顶弹出。程序经过编译运行后,结果如下所示: