顺序栈和链栈实现

注意事项:

顺序栈:

  1. 实现需要使用数组,数组的元素在内存中的存储位置是连续的;
  2. 且需要知道数组的长度才可以使用;无法避免溢出问题;
  3. 当系统给数组分配了内存空间,其他的任务是不能使用这个内存空间的;
  4. 本算法中的顺序栈避免了溢出问题以及空间不能增长的缺陷,使用了动态分配的方法使用连续内存。存储密度 = 1;
  5. 顺序栈的top指针指向的是栈顶的空元素处,top - 1才是指向栈顶元素;不易实现插入和删除操作。

特点:
顺序栈是以一个不断变大的结构体为基址,因为要改变这个结构,所以传递给函数的都是这个的地址。和链表不同的是,他仅仅是传递的结构的指针,所以在函数中直接用->就可以。

#include<stdio.h>//有一个大bug,在用realloc分配内存的过程中,在大小项没有*数据类型的大小
#define STACK_INIT_SIZE 10//导致了每次只增加2字节的量,而不是2字节*4字节
#define STACK_INCREAMENT 2
 
typedef struct SqStack//顺序表是一个以基址为核心的数组,每次操作针对传递基址。根据需求空间,伪动态一次分配少量空间。建立一个结构体,里面包括了基址指针和栈顶指针以及基址已分配空间大小(不是已占用空间)
{
	int *base;    //还有另一种简单顺序栈,不需要建立结构,只需要一个基本数组,和一个代表栈顶下标的整形变量。BiTree SqStack[100];int top=-1; SqStack[++top] = t;这是非递归遍历时,临时建立的栈结构,后者是代替了push函数。t =SqStack[top--]为pop函数。Top == -1代表栈空。
 
 
	int *top;
	int stacksize; //需要这个结构成员来判断是否分配的空间够用
}SqStack; //不需要指向结构变量的指针,只需要传递结构地址。
void Traverse(SqStack s);
void Push(SqStack *s, int e);//相当于顺序表的插入
void Pop(SqStack *s, int *e);//相当于顺序表的删除
void InitStack(SqStack *s);
void Gettop(SqStack s);
int main()
{
	SqStack s;
	int i;
	int e;
	InitStack(&s);
	for (i = 1; i <= 12;i++)
		Push(&s, i);
	printf("the element of stack is :\n");
	Traverse(s);
	getchar();
	return 0;
}
void InitStack(SqStack *s)
{
	s->base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
	if (!s->base)
		exit(1);
	s->top = s->base;
	s->stacksize = STACK_INIT_SIZE;
}
 
void Push(SqStack *s, int e)
{
	if (s->top - s->base >= s->stacksize)
	{
		s->base = (int *)realloc(s->base, (s->stacksize + STACK_INCREAMENT) *
			sizeof(int));
		if (!s->base)
			exit(1);
		s->top = s->base + s->stacksize;
		s->stacksize += STACK_INCREAMENT;
 
	}
	*(s->top)++ = e;
 
}
 
void Pop(SqStack *s, int *e)
{
	if (s->top == s->base)
		exit(1);
	(*e) = *--(s->top);
}
void Traverse(SqStack s)
{
	int *q = s.base;
	while (s.top > q)
		printf("%d ", *q++);
}
 
int SqStacklength(SqStack s)
{
	return s.top - s.base;
}
 
void Gettop(SqStack s, int *e)
{
	if (s.top <= s.base)
		exit(1);
	else
		*e = *(s.top - 1);
}

链栈:

  1. 实现使用链表,链表的元素存储在不同的地址;
  2. 动态申请地址,即可以以非常小的内存空间开始;
  3. 当某项不使用内存时,可以将内存返还给系统;
  4. 存储密度<1;链栈的top指针相当于链表中的head指针,即指向实在的元素;
  5. 相比于顺序栈易实现插入和删除操作且不易出现栈满的情况。

特点:
(易于实现)入栈使用头插法,其余都与链表差不多。头插头删
链栈最好设置有头结点的链表结构,因为都是在头部插入结点,所以如没有头结点,需要使用指向头指针的指针来用来传递函数参数。

#include<stdio.h>
#include<stdlib.h>
 
typedef struct SNode
{
	int data;
	struct SNode * next;
}SNode, *LinkStack;
 
LinkStack Creat();
void Push(LinkStack s, int e);
void Pop(LinkStack s, int *e);
void Traverse(LinkStack s);
 
int main()
{
	LinkStack s = Creat();
	Push(s, 5);
	printf("After push:\n");
	Traverse(s);
	printf("After Pop:\n");
	int e;
	Pop(s, &e);
	Traverse(s);
	printf("the number e is:%d", e);
	return 0;
}
LinkStack Creat()
{
	LinkStack s = (LinkStack)malloc(sizeof(SNode));
	s->next = NULL;
	s->data = -1;
	int i;
	for (i = 1; i <= 10;i++)
		Push(s, i);
	return s;
}
void Push(LinkStack s, int e)//相当于插入
{
	LinkStack p = (LinkStack)malloc(sizeof(SNode));
	p->data = e;
	p->next = s->next;
	s->next = p;
}
void Pop(LinkStack s, int *e)//相当于删除
{
	if (s)
	{
		LinkStack p = s->next;
		s->next = p->next;
		(*e) = p->data;
		free(p);
	}
	else
		exit(1);
}
 
void Traverse(LinkStack s)
{
	LinkStack q = s->next;
	while (q)
	{
		printf("%d ", q->data);
		q = q->next;
	}
	printf("\n");
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值