1 基本概念

栈是限定仅在表尾进行插入或删除操作的线性表。表头称为栈底,表尾称为栈顶,不含元素的空栈叫做空栈。栈具有后进先出的特点。

2 抽象数据类型(ADT)

数据对象:{a1,a2,.....,an},每个元素类型为DataType,与线性表类似。

数据关系:除第一个元素外,每一个元素有且只有一个直接前驱元素;除最后一个元素外,每个元素有且只有一个直接后驱。一对一  的对应关系。第一个元素被称为栈底元素,最后一个元素为栈顶元素。

基本操作:

                    InitStack(*S): 建立一个空栈。

                   DestroyStack(*S): 若栈存在,则销毁它。

                   ClearStack(*S): 将栈清空。

                   StackEmpty(S): 若栈为空,返回true,否则返回false。

                   GetTop(S,*e): 若栈存在且非空,则返回栈顶元素值给e。

                   Push(*S,e): 插入e为栈顶元素。

                   Pop(*S,*e): 删除栈顶元素,并将值返回给e。

                   StackLength(S): 返回栈S的元素个数。

3 顺序存储:

#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
#include <stdlib.h>
#include <stdio.h> 
//栈的顺序存储结构定义
#define STACK_INIT_SIZE 100    //栈的初始存储空间容量 
#define STACKINCREMENT 10      //当栈满时,每次新增的存储空间增量 
typedef int ElemType;         //元素的数据类型根据实际情况而定,这里假设为int 
typedef struct Stack
{
	ElemType *base;          //栈底指针,始终指向栈底,当指向NULL时,则栈结构不存在 
	ElemType *top;           //栈顶指针,指向栈顶元素的下一个元素,当栈为空时,栈顶指针指向栈底 
	int stacksize;           //当前栈的存储空间容量 
}SqStack;

int InitStack(SqStack*S)         //初始化创建一个栈 
{
	if (!(S->base=(ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType)))) return ERROR;  //申请存储空间 
	S->top=S->base;            //栈为空,栈顶指针指向栈底 
	S->stacksize=STACK_INIT_SIZE;  //当前栈的存储空间容量为初始存储空间 
	return OK;
}

int DestroyStack(SqStack*S)    //销毁栈 
{
	if (S->base) 
	{
		S->stacksize=0;
		free(S->base);      //释放栈的基地址 
		S->base=NULL;
		S->top=NULL; 
	}
	return OK;
}

int ClearStack(SqStack*S)    //清空栈 
{
	while(S->base!=S->top)
	{
		S->top--;
	}
	return OK;
}

int StackEmpty(SqStack S)   //验证栈是否为空 
{
	if (S.base==S.top) return TRUE;
	return FALSE; 
}

int GetTop(SqStack S,ElemType*e)   //得到栈顶元素 
{
	if (S.base==S.top) return ERROR;
	*e=*(S.top-1);
	return OK;
}

int Push(SqStack *S,ElemType e)   //将元素e压栈 
{
	if ((S->top-S->base)>=S->stacksize)  //若栈已满 
	{
		S->stacksize+=STACKINCREMENT;
		if (!(S->base=(ElemType*)realloc(S->base,S->stacksize*sizeof(ElemType)))) return ERROR;    //申请新的栈存储空间 
	}
	*(S->top)=e;
	S->top++;
	return OK;
}

int POP(SqStack *S,ElemType*e)  //将栈顶元素出栈,并将值返回给e 
{
	if (S->base==S->top) return ERROR;
	*e=*(--S->top);
	return OK;
}

int StackLength(SqStack S)  //返回栈的长度 
{
	return (S.top-S.base);
}

int main()   //验证
{
	SqStack S;
	int e,choice; 
	do{
		printf("输入操作: 1.返回栈长度 2.进栈 3.出栈 4.得到栈顶元素 5.验证栈是否为空 6.清空栈 7.创建栈 8.销毁栈\n");
		scanf("%d",&choice);
		switch (choice)
		{
			case 1:
			{
				e=StackLength(S);
				printf("%d\n",e);
				break;
			}
			case 2:
			{
				printf("输入进栈元素值\n");
				scanf("%d",&e);
				Push(&S,e);
				break;
			}
			case 3:
			{
				POP(&S,&e);
				printf("%d\n",e);
				break;
			}
			case 4:
			{
				GetTop(S,&e);
				printf("%d\n",e);
				break;
			}
			case 5:
			{
				printf("%d\n",StackEmpty(S));
				break;
			}
			case 6:
			{
				ClearStack(&S);
				break;
			}
			case 7:
			{
				InitStack(&S);
				break;
			}
			case 8:
			{
				DestroyStack(&S);
				break;
			}
		}
	}while(choice!=8); 
	return 0;
}

4 链式存储

#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
#include <stdlib.h>
#include <stdio.h> 
//栈的链式存储结构定义
typedef int ElemType;         //元素的数据类型根据实际情况而定,这里假设为int 
typedef struct Node
{
	ElemType data;
	struct Node*next;
}Node,*LinkStack;

int InitStack(LinkStack*S)
{
	(*S)=(Node*)malloc(sizeof(Node));      //头结点 
	if (!(*S)) return ERROR;
	(*S)->next=NULL;                        
	(*S)->data=0;                         //头结点数据域用来存储栈长度 
}

int Push(LinkStack *S,ElemType e)   //将元素e压栈 
{
	Node*p;
	p=(Node*)malloc(sizeof(Node));
	if (!p) return ERROR;
	p->data=e;
	p->next=(*S)->next;
	(*S)->next=p;
	(*S)->data++;
	return OK;
}

int POP(LinkStack *S,ElemType*e)  //将栈顶元素出栈,并将值返回给e 
{
	Node*p;
	p=(*S)->next;
	*e=p->data;
	(*S)->next=p->next;
	free(p);
	(*S)->data--;
	return OK;
}

int StackLength(LinkStack S)
{
	return S->data;
}


int main()
{
	LinkStack S;
	Node*p;
	int e,choice; 
	do{
		e=0;
		printf("输入操作: 0.退出 1.返回栈长度 2.进栈 3.出栈 4.初始化栈\n");
		scanf("%d",&choice);
		switch (choice)
		{
			case 1:
			{
				e=StackLength(S);
				printf("%d\n",e);
				break;
			}
			case 2:
			{
				printf("输入进栈元素值\n");
				scanf("%d",&e);
				Push(&S,e);
				break;
			}
			case 3:
			{
				POP(&S,&e);
				printf("%d\n",e);
				break;
			}
			case 4:
			{
				InitStack(&S);
				break;
			}
		}
		p=S->next;
		printf("[");
		while(p)
		{
			printf("%d ",p->data);
			p=p->next;
		}
		printf("]\n");
	}while(choice!=0); 
	return 0;
}

4 总结

对于顺序栈和链栈,它们时间复杂度都一样,均为O(1)。顺序栈存取更简单方便,但链栈对于顺序栈来说,其长度可无限制。因此在处理元素数量变化不大的情况下,使用顺序栈更方便,否则最好使用链栈。



  

                  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值