栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数据结构--2.1 栈

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构--2.1 栈

数据结构--栈及其应用
    • 老师版
      • 创建
      • 压栈
      • 出栈
      • 测试代码
      • 运行结果
    • 自己版
      • 创建
      • 压栈
      • 出栈
      • 运行结果
    • 总结
    • 栈的应用--括号匹配
      • 运行结果

今天敲得是栈。栈是一种特殊的存储方式,这种方式就像往箱子里面放东西,先放进去的后拿出来,后放进去的先拿出来。老师是用数组的形式实现,我用链表的形式实现。来看代码吧。

老师版 创建
#include 
#include 

#define STACK_MAX_SIZE 10

typedef struct CharStack{
	int top;
	int data[STACK_MAX_SIZE];
}*CharStackPtr;

CharStackPtr CharStackInit()
{
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(CharStack));
	resultPtr->top=-1;
	
	return resultPtr;
}

我们在结构体里设置了一个名为top的变量,它的作用就是始终指向最顶部,也就是最后放进去的元素。

压栈


这副动态图很形象的解释了压榨,每放入一个元素,都使top往后移一位,使之始终指向栈顶的元素。

void push(CharStackPtr paraStackPtr,int paraValue)
{
	if((paraStackPtr->top)>=STACK_MAX_SIZE -1)
	{
		printf("Can not push element:stack is full.");
		return;
	}

	paraStackPtr->top ++;

	paraStackPtr->data[paraStackPtr->top] = paraValue;
}
出栈


出栈操作也十分简单,元素移出,让top前移。

char pop(CharStackPtr paraStackPtr)
{
	if(paraStackPtr->top<0)
	{
		printf("Can not pop element:stack empty.rn");
		return '';
	}
	
	paraStackPtr->top --;
	
	return paraStackPtr->data[paraStackPtr->data +1];
} 
测试代码
void pushPopTest() {
	char ch;
	int i;
	
    printf("---- pushPopTest begins. ----rn");

    CharStackPtr tempStack = CharStackInit();
    printf("After initialization, the stack is: ");
	outputStack(tempStack);

	for ( ch = 'a'; ch < 'm'; ch ++) {
		printf("Pushing %c.rn", ch);
		push(tempStack, ch);
		outputStack(tempStack);
	}
	for ( i = 0; i < 3; i ++) {
		ch = pop(tempStack);
		printf("Pop %c.rn", ch);
		outputStack(tempStack);
	}

    printf("---- pushPopTest ends. ----rn");
}

int main() {
	pushPopTest();
}
运行结果
---- pushPopTest begins. ----
After initialization, the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Can not push element:stack is full.a b c d e f g h i j
Pushing l.
Can not push element:stack is full.a b c d e f g h i j
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
---- pushPopTest ends. ----
自己版

我自己写了链式栈的基本算法的代码,附在下方

创建

链式栈需要两个结构体,一个定义节点,另外一个定义栈顶和栈底。

typedef struct Node
{
	int data;
	struct Node *next;
}NODE,*PNODE;

typedef struct Stack
{
	PNODE pTop;
	PNODE pBottom;
}STACK,*PSTACK;

void initStack(PSTACK pS)
{
	printf("initrn");
	
	pS->pTop = (PNODE)malloc(sizeof(NODE));
	
	pS->pBottom = pS->pTop ;
	pS->pTop ->next=NULL;
	
	return;
}

在写创建这代码的时候,我遇到了一个令我百思不得其解的问题。因为创建其实理解起来很简单,让栈顶和栈底相等,然后栈顶指向为空即可。
一开始,我让栈顶和栈底相等是这样写的:

pS->pTop = pS->pBottom ;

但是却怎么也无法压栈和出栈,我甚至为此把所有代码重新敲了一遍。后来,再一次对我的代码的修改时我将这两者互换了位置,突然就全部都运行了。
然后我看了这一小段代码的网课,原来在我已经给pTop动态分配了内存,但是pBottom却仍然是一堆垃圾值,而我们应该给pBottom赋值并且使他们指向同一处。而把pTop赋值给pBottom才能使他们指向同一处。

压栈
void pushStack(PSTACK pS,int val)
{
	printf("pushrn");
	
	PNODE p;
	p=(PNODE)malloc(sizeof(NODE));
	
	p->data =val;
	p->next =pS->pTop ;
	pS->pTop =p;
}
出栈
void popStack(PSTACK pS)
{
	printf("poprn");
	
	PNODE p;
	p=(PNODE)malloc(sizeof(NODE));
	
	p=pS->pTop ;
	pS->pTop =p->next ;
	free(p);
	p=NULL;
}
运行结果
init
11
push
push
push
push
22
print
4 3 2 1 33
pop
print
3 2 1
总结

实际上栈的算法很好理解,无非是先进后出,后进先出八字。

但是栈虽然简单,却能解决生活中很多问题,比如下面的括号匹配问题。

栈的应用–括号匹配

由于栈的实现和之前的完全一样,所以这里我只列出最主要的括号匹配部分的代码。

bool bracketMatching(char* String, int Length)
{
	CharStackPtr stack = initStack();
	int i;
	
	char tempch,popch;
	pushStack(stack,'#');
	
	for(i=0;i
		tempch=String[i];
		
		switch(tempch)
		{
			case '(':
			case '[':
			case '{':
				pushStack(stack,tempch);
				break;
			case')':
				popch=popStack(stack);
				if(popch!='(')
				{
					return false;
				}	
				break;	
			case']':
				popch=popStack(stack);
				if(popch!='[')
				{
					return false;
				}	
				break;
			case'}':
				popch=popStack(stack);
				if(popch!='}')
				{
					return false;
				}	
				break;
			default:
				break;
		}
	}
	
	popch=popStack(stack);
	if(popch!='#')
	{
		return false;
	}
	
	return true;
}

这一段代码的逻辑思想也很简单,理解之后敲起来就十分顺手。当我们在表达式中遇到了‘(,【,}’这几个括号时,我们进行压栈操作,将这几个括号存入栈中,接着,如果我们遇到了‘),】,}’这几个括号中的一个时,我们进行出栈操作,如果此时弹出的元素和此时遇到的括号对应,就接着循环找到下一个括号,否则就返回‘0’,也就是不匹配。
在代码中,我们还设置了“#”标识符,当我们匹配结束却仍然没有弹出“#”,证明我们多了一个括号没有匹配到,也会返回“0”。
另外,代码中的变量和老师的略有差异,因为我是自己敲得,所以改变了部分变量名。

运行结果
Is the expression '[2 + (1 - 3)] * 4' bracket matching? 1
Is the expression '( )  )' bracket matching? 0
Is the expression '()()(())' bracket matching? 1
Is the expression '({}[])' bracket matching? 0
Is the expression ')(' bracket matching? 0
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873013.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号