C语言实现栈数据结构操作

定义:栈是限定仅在表尾进行插入和删除操作的线性表。

把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表,简称为LIFO。

栈的插入操作,叫做进栈,也称为压栈或者入栈。

栈的删除操作,叫做出栈,也称为弹栈。

 

栈的顺序存储结构

因为栈是线性表的一种特殊形式,所以用数组实现栈的顺序存储结构。

我们约定,下标为0的一端作为栈底。定义一个top变量来指示栈顶元素在数组中的位置。约定把空栈的判定条件定为top等于-1。

栈的结构定义:

#define MAXSIZE 100;
typedef int SElemType;
typedef struct
{
	SElemType data[MAXSIZE];
	int top;  /*用于栈顶指针*/ 
}SqStack;


栈的顺序存储结构-----进栈

C语言代码如下:

/*插入元素e为新的栈顶元素*/
int Push(SqStack *S, SElemType e)
{
	if (S->top == MAXSIZE - 1)
	{
		return 0;
	}
	S->top++;
	S->data[S->top] = e;
	return 1;
}


 

栈的顺序存储结构---出栈

C语言代码如下:

/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回1;否则返回0*/
int Pop(SqStack *L, SElemType *e)
{
	if (S->top == -1)
	{
		return 0;
	}
	*e = S->data[S->top];
	return 1; 
}


说明:栈的顺序存储结构的进栈和出栈都没有涉及循环,时间复杂度都为O(1)。

 

 

两栈共享空间

如果有两个相同类型的栈,我们为他们各自开辟了数组空间,极有可能是第一个栈满了 ,再进栈就溢出了,而另一个栈还有很多存储空间空闲。因此我们完全可用一个数组来存储两个栈。

做法:数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈的栈底为栈的末端,即下标为n-1处。这样,两个栈如果增加元素,就是两端点向中间延伸。

我们约定top1和top2是两个栈的栈顶指针。

栈1为空时,top1=-1;栈2空时,top2=n。

当栈满时有top2 = top1+1。

两栈共享空间结构代码如下:

/*两栈共享空间结构*/
typedef struct
{
	SElemType data[MAXSIZE];
	int top1;
	int top2;
}SqDoubleStack;


两栈共享空间的进栈操作

/*插入元素e为新的栈顶元素*/
int Push(SqDoubleStack *S, SElemType e, int stackNumber)
{
	if (S->top1+1==S->top2) /*栈已经满,不能再push新元素*/
	{
		return 0;	
	}
	if (stackNumber == 1) /*栈1有元素进栈*/
	{
		S->data[++S->top1] = e /*若栈1则先top1+1后给数组元素赋值*/ 
	} 
	else if(stackNumber == 2)
	{
		S->data[--S->top2] = e;
	} 
	return 1;
} 


 

两栈共享空间出栈操作

/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回1,否则返回0*/
int Pop(SqDoubleStack *S, SElemType *e, int stackNumber)
{
	if (stackNumber == 1)
	{
		if (S->top1 == -1)
		{
			return 0;
		}
		*e = S->data[S->top1--];
	}
	else if (stackNumber == 2)
	{
		if (S->top2 == MAXSIZE)
		{
			return 0;
		}
		*e = S->data[S->top2++];
	}
	return 1;
} 

说明:使用两栈共享空间这样的数据结构,通常都是当两个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况。当然,这只是针对两个具有相同数据类型的栈的一个设计上的技巧。

 

栈的链式存储结构----简称链栈

由于单链表有头指针,而栈顶指针也是必须的,因此比较好的方法时把栈顶放在单链表的头部。通常对于链栈来说,是不需要头结点的。

链栈的结构定义:

 

typedef int SElemType;
typedef struct StackNode
{
	SElemType data;
	struct StackNode *next; 
}StackNode;
typedef StackNode * LinkStackPtr;

typedef struct LinkStack
{
	LinkStackPtr top;  //栈顶指针 
	int count;
}LinkStack;


链栈的进栈操作:

/*插入元素e为新的栈顶元素*/
int Push(LinkStack *S, SElemType e)
{
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
	s->data = e;
	s->next = S->top;//把当前的栈顶元素赋值给新结点的直接后继
	S->top = s;
	S->count++;
	return 1; 
	
}


链栈的出栈操作:

/*若栈不为空,则删除S的栈顶元素,用e返回其值,并返回1;否则返回0*/
int Pop(LinkStack *S, SElemType *e)
{
	LinkStackPtr p;
	if (S->top == NULL)
	{
		return 0;
	}
	*e = S->top->data;
	p = S->top;
 	S->top = S->top->next;
 	free(p);
 	S->count--;
	return 1; 
}


说明:对于链栈的进栈和出栈操作,它们的时间复杂度都为O(1)。
 

你可能感兴趣的:(数据结构)