栈结构


(自复习用的笔记,参考严老师的数据结构c语言版)

栈(LIFO)

知识点

ADT

参照教材,有9个基本操作
- InitStack
- DestroyStack
- ClearStack	(注意栈的**空状态**以及**不存在**状态)
- StackEmpty
- GetTop
- Push
- Pop
- StackTraverse

栈的表示及实现

  1. 顺序存储
    当设置base恒指向栈底时

     - 设置栈底指针base始终指向栈底与栈顶指针top(当入栈时++,出栈时--),则top始终指向栈顶元素的下一个位置(top->next为栈顶元素)。
     - 栈空时,top=base;栈结构不存在时,base=NULL;
     - top->next为栈顶结点
     - 初始容量、储存空间分配增量		
     - 多个栈共用一个静态存储空间则有对整个栈的操作
    

    当不设置base而数组[0]不放置元素时

     		- 此时top指向即栈顶元素
     		- 最大容量为数组长度-1
     		- 栈空时top=0
    
typedef struct{
	SElemType	*base;	//栈构造前和销毁后,base的值为NULL;
	SElemType	*top;	
	int stacksize;	//当前已分配的存储空间
}SqStack;

  1. 链式存储

    - 显然栈顶元素作为表头对其插入、删除操作均较为方便。
    

链式代码实现

注意注释

# include<stdio.h>
# include<stdlib.h>

//增强可读性!nice!学到了!
# define TRUE 1
# define OK 1
# define FALSE 0
# define ERROR 0

/*结点定义*/
typedef int ElemType;
typedef int Status;
typedef struct NODE
{
	ElemType *elem;
	struct NODE *next;
}NODE;
typedef NODE* STACK;


/***************************************************函数声明************************************************************/
STACK CreateStack();
void DestroyStack(STACK S);
void ClearStack(STACK S);
Status StackEmpty(STACK S);
int StackLength(STACK S);
NODE* GetTop(STACK S);
STACK Push(STACK S, ElemType* e);
ElemType* Pop(STACK S);
Status StackTraverse(STACK S);
void StackVisit(NODE* p);
/***************************************************函数定义************************************************************/

//构造空栈,返回base
STACK CreateStack()
{
	NODE *base, *top;
	base = (NODE*)malloc(sizeof(NODE));
	base->next = NULL; // 注意初始化设为NULL
	top = base;
	return base;
}

//销毁栈
void DestroyStack(STACK S)
{
	if (S != NULL)
	{
		ClearStack(S);
		free(S);
	}
	else
		printf("Error!Can`t destroy a NULL STACK!");
}

//清空栈
void ClearStack(STACK S)
{
	NODE *p;
	if (S != NULL)
	{
		p = S->next;
		while (p->next != NULL)
		{
			free(S);
			S = p;
			p = p->next;
		}
		free(S);
		S = p;
	}
	else
		printf("Error!Can`t clear a NULL stack!");
}

//判断是否为空栈
Status StackEmpty(STACK S)
{
	if (S)
	{
		if (S->next == NULL)
			return TRUE;
		return FALSE;
	}
	fprintf(stderr, "ERROR!The stack doesn't exist!");
	return ERROR;	//学会用宏定义增加代码可读性
}

//返回栈长
int StackLength(STACK S)
{
	int len = 0;
	if (S)
	{
		while (S->next != NULL)
		{
			len++;
			S = S->next;
		}
		return len;
	}
	fprintf(stderr, "ERROR!The stack doesn't exist!");
	return -1;
}

//返回栈顶元素
NODE* GetTop(STACK S)
{
	if (S)
	{
		if (S->next)
		{
			return S;
		}
		printf("The stack is empty!");
		return NULL;
	}
	fprintf(stderr, "ERROR!The stack soesn't exist!");
	return NULL;
}

//插入元素作为新栈顶
STACK Push(STACK S, ElemType* e)
{
	NODE* p;
	p = (NODE*)malloc(sizeof(NODE*));
	p->next = S;
	return p;
}

//删除栈顶元素,并返回数据指针
ElemType* Pop(STACK S)
{
	NODE *p = NULL;
	if (S->next)
	{
		p = S;
		S = S->next;
		return p->elem;
	}
	fprintf(stderr, "Stack doesn't exist!");
	return NULL;
}
Status StackTraverse(STACK S)
{
	NODE *p;
	p = S;
	if (S->next)
	{
		while (p->next)
		{
			StackVisit(p);
			p = p->next;
		}
	}
}

void StackVisit(NODE* p)
{
	printf("%d", *(p->elem));
}


应用

  1. 数制转换
void conversion()
{
	//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
	int N, *elem;
	elem = (int*)malloc(sizeof(int));
	STACK S;
	S = CreateStack();
	scanf_s("%d", &N);
	while (N)
	{
		*elem = N % 8;
		S = Push(S, elem);
		N = N / 8;	//注意关系
	}
	while (!StackEmpty(S))
	{
		elem = Pop(S,&S);
		printf("%d", *elem);
		free(elem);
	}
}//conversion
  1. 括号匹配检验
BOOL correct(char ext[], int i)
{
	STACK S;
	int j = 0;
	S = CreateStack();
	for (j = 0; j < i; j++)
	{
		int mark = 0,*mark2 = NULL;
		mark = IsBrackets(ext[j]);
		if (mark >= 1 && mark <= 3)
		{
			S = Push(S, &mark);
		}
		else if (mark >= 7 && mark <= 9)
		{
			mark2 = Pop(S,&S);//注意这个地方要传入指针的地址奥
			if ((*mark2) + mark != 10)
			{
				fprintf(stderr, "ERROR!");
				return -1;
			}
			free(mark2);
		}
	}
	if (S->next == NULL)
		return TRUE;
	return FALSE;
}
int IsBrackets(char a)
{
	switch (a) {
	case '(':return 1;
	case '[':return 2;
	case '{':return 3;
	case ')':return 9;
	case']':return 8;
	case '}':return 7;
	default:return 0;
	}
}

  • 行编辑程序
void LineEdit()
{
	STACK S=CreatStack();
	ch = getchar();
	while(ch!=EOF)
	{
		while(ch!=EOF&&ch!='\n')
		{
			switch(ch){
				case '#':Pop(S,c);
				case '@':ClearStack(S);
				default:Push(S,ch);
			}//switch
			ch=getchar();
		}//while
	}//while EOF

}//LineEdit
  • 迷宫求解
void FindRoad(STACK S, int mark[][COL], int maze[][COL])
{
	int i = 1, j = 1, v = 0;
	int g, h;
	int V[8][2] = { 0,1,1,1,1,0,1,-1,0,-1,-1,-1,-1,0,-1,1 };
	NODE *e;

	S = Push(S,i,j,v);
	mark[1][1] = 1;
	do {
		g = i + V[v][0];
		h = j + V[v][1];
		if ((g == ROW - 2) && (h == COL - 2)&&maze[ROW-2][COL-2]==0)
		{
			output(S);
			return;
		}
		if (maze[g][h] == 0 && mark[g][h] == 0)
		{
			S = Push(S, g, h, v);
			i = g;
			j = h;
			v = 0;
			mark[g][h] = 1;
		}
		else if (maze[g][h] == 1 || mark[g][h] == 1)
		{
			if (v == 7&&S&&!StackEmpty(S))
			{
				e = Pop(S, &S);
				e = GetTop(S);
				i = e->elem->i;
				j = e->elem->j;
				v = e->elem->v + 1;
			}
			else
			{
				v += 1;
			}
		}
	} while (!StackEmpty(S)||v!=8);
	printf("路径不存在!");
	return;
}
  • 判断字符串是否中心对称
  • 汉诺塔
  • 表达式求值(中缀转换为前后缀)重点
    首先对算符之间有优先级的定义。
    基本思想:
    1. 设置两个栈,OPND和OPTR。OPND为寄存操作数以及运算结果(都是数字),OPNR寄存运算符。
    2. 依次读入表达式中的数字、字符。如果是操作数则进栈OPND,若是运算符则和OPNR栈顶的运算符的优先级作比较:
      若优先级低于栈顶的操作符,则栈顶元素出栈并对操作数的最上面两个数出栈后进行相应的运算,运算结果存储于OPND中。
      直至表达式读取结束且OPND栈为空,OPNR栈的仅剩的一个元素则为运算结果。
      注:对于(),一旦相遇则说明括号内的运算已经完成,则可以出栈直接读取下一个操作符。(消消乐)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值