您的位置:首页 > 编程语言 > Go语言

introduction to algorithms data structure lesson_1 stack

2014-09-27 18:13 435 查看
前面介绍了各种常见的排序算法,第二部分介绍基本的data structure 数据结构

lesson 1 stack

栈是一种动态集合,栈实现LIFO(last in first out)的策略。

主要有push pop两种操作




其他的一些基本操作如:1.判断栈是否为空 IsStackEmpty(myStack *stack)

2.获取栈顶元素 GetTop(myStack *stack,Item *pitem)

3.建立一个栈 InitStack()

4.销毁一个栈 DestroyStack(myStack *stack)

5.置空一个栈 ClearStack(myStack *stack)

6.返回栈的大小 GetStackSize(myStack *stack);

7.顺序遍历一个栈 stackvisit(myStack *stack,void (*visit)(Item item));

那么如何用C/C++来实现这样一种数据结构呢。

最简单的是采用链式存储的方法建立一个栈

一个栈的结构包括 栈顶指针top以及栈的大小size

那么c语言就可以这样定义数据类型啦



/******链式栈的C语言实现***********/
typedef  int Item;           //数据类型
typedef struct  Node *PNode; //链式指针
//栈节点类型
typedef struct  Node
{
	Item data;
	PNode down;

}node;
//栈
typedef struct myStack
{
	PNode top;
	int size;
}MyStack;
其中top指针是一种链式存储结构,其down域指向栈顶下面的一个元素,栈元素存在data域中

基本操作函数实现为:mystack.h

//构造空栈
myStack *InitStack();
//销毁一个栈
void DestroyStack(myStack *stack);
//判断栈是否为空
bool IsStackEmpty(myStack *stack);
//将栈置空
void ClearStack(myStack *stack);
//返回栈大小
int  GetStackSize(myStack *stack);
// 返回栈顶元素
void GetTop(myStack *stack,Item *pitem);
//入栈
void push(myStack *stack,Item item);
//出栈
void pop(myStack *stack,Item *pitem);
//顺序访问Visit函数
void stackvisit(myStack *stack,void (*visit)(Item item));//此处后面会详细解释
下面实现这些函数:mystack.c(mystack.cpp)

//构造空栈
myStack  *InitStack()
{
	myStack *ps=(myStack *)malloc(sizeof(myStack));
	if (ps!=NULL)
	{
		ps->top=NULL;
		ps->size=0;
	}
	return ps;
}
//销毁一个栈
void DestroyStack(myStack *stack)
{
   if (!IsStackEmpty(stack))
	   ClearStack(stack);
   free(stack);
}
//判断栈是否为空
bool IsStackEmpty(myStack *stack)
{
	if (stack->size==0&&stack->top==NULL)
		return true;
	else
		return false;
}
//将栈置空
void ClearStack(myStack *stack)
{
	while(!IsStackEmpty(stack))
		pop(stack,NULL);
}
//返回栈大小
int  GetStackSize(myStack *stack)
{
	return stack->size;
}
// 返回栈顶元素
void  GetTop(myStack *stack,Item *pitem)
{
	if (!IsStackEmpty(stack)&&pitem!=NULL)
		*pitem=stack->top->data;
}
//入栈
void push(myStack *stack,Item item)
{
	PNode pnode=(PNode)malloc(sizeof(Node));
	if (pnode==NULL)
		return;
	pnode->data=item;
	pnode->down=stack->top;
	stack->top=pnode;
	stack->size++;
}
//出栈
void pop(myStack *stack,Item *pitem)
{
	PNode pnode=stack->top;
	if (!IsStackEmpty(stack)&&pnode!=NULL)
	{
		if (pitem!=NULL)
			*pitem=pnode->data;
			
		stack->top=pnode->down;
		stack->size--;
		free(pnode);
	}
}
void stackvisit(myStack *stack,void (*visit)(Item item))//此处后面详细解释
{
	if (IsStackEmpty(stack))
		return;
	PNode pnode=stack->top;
	int size=stack->size;
	while(size--)
	{
		visit(pnode->data);
		pnode=pnode->down;
	}
}


然后是测试栈:

int _tmain(int argc, _TCHAR* argv[])
{
	myStack *mystack=InitStack();
	Item i,item;
	if (mystack==NULL)
		return 0;
	for (i=0;i<10;i++)
	{
		push(mystack,i);
		GetTop(mystack,&item);
		printf("%d\n",item);
	}
	printf("出栈顺序\n");
	printf("size=%d\n",GetStackSize(mystack));
	stackvisit(mystack,print);//print为自己写的打印函数 形式为print(Item item)
	system("pause");
	return 0;
}


运行结果:


基本操作就是如此。

其中最关键的是顺序遍历函数中visit的问题,这是一个涉及函数指针的问题。

void stackvisit(myStack *stack,void (*visit)(Item item))//此处后面详细解释
stackvisit(mystack,print);



测试中用到的print为自己实现的函数,且必须为visit(Item item)的形式,才能编译通过

void (*visit)(Item item) 为函数作为函数的参数。

其中 void 为被传函数的返回类型 (*visit)必须用括号,这样才表示一个函数指针,即参数为一个函数。函数指针不同于数据指针,它所指向的不是数据,而是某个函数的入口地址,或某段代码的入口。(Item item)是visit函数的形参方式。在后面的调用中,传入的函数比如我使用的print,其形式必须与定义的void (*visit)(Item item)完全一样,否则会报错。

而函数作为形参调用方式即为函数名,可以看作是一个指针。

最后关于栈的一些经典应用,比如实现简单的表达式计算(括号匹配)、数制转换、迷宫问题将在后面逐一介绍,以加深对栈的理解

注:参考博客 :http://blog.csdn.net/hopeyouknow/article/details/6725049
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: