数据结构笔记(三)——栈

算是一种表(list),但是它只能在表的末端(栈顶top)进行操作,栈的特点是后进先出(LIFO)。

实现栈同样可以用链表和数组,一般大家比较喜欢用数组,避免了指针,而且没有分配内存的时间开销,不过需要事先声明数组大小,所有涉及到数组的都存在这个问题。

一、用链表实现

链表实现栈要记住的是表头为栈顶,因为稍微模拟一下就可以知道,如果把链表末尾当做栈顶,那么在出栈的时候栈无法指向这个结点的前一个结点。

StackList.h

#pragma once
#include<iostream>
using namespace std;
struct Node;
typedef int ElementType;
typedef Node* PtrToNode;
typedef PtrToNode Stack;
Stack createStack();
void makeEmpty(Stack);
void dispose(Stack);
void push(ElementType, Stack);
ElementType pop(Stack);
ElementType top(Stack);
void printStack(Stack);
struct Node
{
	ElementType data;
	PtrToNode next;
};

StackList.cpp

#include "stdafx.h"
#include "StackList.h"
Stack createStack() 
{
	Stack s;
	s = (Stack)malloc(sizeof(struct Node));
	if (s==nullptr)
	{
		cout << "space error" << endl;
		return s;
	}
	s->next = nullptr;
	makeEmpty(s);
	return s;
}
void makeEmpty(Stack s) 
{
	if (s==nullptr)
	{
		return;
	}
	while ((s->next)!=nullptr)
	{
		pop(s);
	}
}
void dispose(Stack s)
{
	if (s == nullptr)
		return;
	makeEmpty(s);
	free(s);
}
void push(ElementType e, Stack s)
{
	Node *node = (Node*)malloc(sizeof(struct Node));
	if (node==nullptr)
	{
		cout << "space error" << endl;
	}
	node->data = e;
	node->next = s->next;
	s->next = node;
}
ElementType pop(Stack s)
{
	if (s->next!=nullptr)
	{
		Node *node = s->next;
		ElementType e = node->data;
		s->next = node->next;
		free(node);
		return e;
	}
	return -1;
	
}
ElementType top(Stack s)
{
	if ((s==nullptr) || (s->next == nullptr))
	{
		cout << "empty" << endl;
		return -1;
	}
	return s->next->data;
}
void printStack(Stack s) 
{
	if (s == nullptr)
	{
		return;
	}
	Node *ptr = s->next;
	while (ptr!=nullptr)
	{
		cout << ptr->data << endl;
		ptr = ptr->next;
	}
}

二、用数组实现

StackArray.h

#pragma once
#include<iostream>
using namespace std;
struct Node;
typedef int ElementType;
typedef Node* Stack;
bool isFull(Stack);
bool isEmpty(Stack);
Stack createStack(int max_capacity);
void makeEmpty(Stack);
void dispose(Stack);
void push(ElementType, Stack);
ElementType pop(Stack);
ElementType top(Stack);
void printStack(Stack);
struct Node 
{
	int capacity;
	int top_of_stack;
	ElementType *array_data;
};

StackArray.cpp

#include "stdafx.h"
#include "StackArray.h"
bool isFull(Stack s)
{
	return (s->top_of_stack) >= (s->capacity);
}
bool isEmpty(Stack s)
{
	return s->top_of_stack <= -1;
}
Stack createStack(int max_capacity)
{
	Stack s;
	s = (Stack)malloc(sizeof(struct Node));
	if (s==nullptr)
	{
		return s;
	}
	s->array_data = (ElementType*)malloc(sizeof(ElementType)*max_capacity);
	if (s->array_data==nullptr)
	{
		return nullptr;
	}
	s->capacity = max_capacity;
	makeEmpty(s);
	return s;
}
void makeEmpty(Stack s)
{
	if (s==nullptr)
	{
		return;
	}
	s->top_of_stack = -1;
}
void dispose(Stack s)
{
	makeEmpty(s);
	free(s->array_data);
	free(s);
	s->capacity = 0;
}
void push(ElementType e, Stack s)
{
	if (isFull(s))
	{
		return;
	}
	s->array_data[++s->top_of_stack] = e;
}
ElementType pop(Stack s)
{
	if (!isEmpty(s))
	{
		return s->array_data[s->top_of_stack--];
	}
	return -1;
}
ElementType top(Stack s)
{
	if (!isEmpty(s))
	{
		return s->array_data[s->top_of_stack];
	}
	return -1;
}
void printStack(Stack s)
{
	if (!isEmpty(s))
	{
		for (int i=0;i<=(s->top_of_stack);++i)
		{
			std::cout << (s->array_data)[i] << std::endl;
		}
	}
}

注:程序中包含的vld.h是一个内存泄漏的检查工具,只需要把路径放在包含目录,include头文件就可以检测是否泄漏,一般快速的检查就是不打断点debug一下,在输出窗口会输出内存泄漏的信息。

三、应用

(1)检查括号匹配的简单代码

bool isMatching(string &str)
{
	Stack s = createStack(100);
	char e;
	for (auto c:str)
	{
		switch (c)
		{
		case '{':
		case '(':
		case '[':
			push(c, s);
			break;
		case '}':
			if (isEmpty(s)||(e=pop(s)) !='{')
				return false;
			break;
		case ']':
			if (isEmpty(s) || (e = pop(s)) != '[')
				return false;
			break;
		case ')':
			if (isEmpty(s) || (e = pop(s)) != '(')
				return false;
			break;
		}
	}
	return true;
}

(2)整数的四则运算

//整数四则运算
int computeInt(int a, int b,char c)
{
	int res = -1;
	switch (c)
	{
	case '+':
		res = a + b;
		break;
	case '-':
		res = a - b;
		break;
	case '*':
		res = a*b;
		break;
	case '/':
		if (b!=0)
		{
			res = a / b;
			break;
		}
		break;
	default:
		break;
	}
	return res;
}
//计算后缀表达式表示的式子
int computeSuffix(string &str)
{
	Stack s = createStack(100);
	int a, b,d;
	for (auto c:str)
	{
		if (isdigit(c))
		{
			d = c - '0';
			push(d, s);
		}
		else
		{
			b = pop(s);
			a = pop(s);
			push(computeInt(a, b, c),s);
		}
	}
	return pop(s);
}
bool isPrior(char a,char b)
{
	if (a=='(')
	{
		return true;
	}
	if ( (b == '*' || a == '/')&&(a=='+'||b=='-'))
	{
		return true;
	}
	return false;
}
//中缀转后缀表达式
string infixToSuffix(string &str)
{
	string prefix;
	int d;
	Stack s = createStack(100);
	for (auto c:str)
	{
		if (isdigit(c))
		{
			prefix += c;
		}
		else if (isEmpty(s)|| c == '(')
		{
			push(c, s);
		}
		else if (c==')')
		{
			char popout = pop(s);
			while (popout!='(')
			{
				prefix += popout;
				popout = pop(s);
			}
		}
		else if (isPrior(top(s),c))
		{
			push(c, s);
		}
		else
		{
			prefix += pop(s);
			push(c, s);
		}
	}
	while (!isEmpty(s))
	{
		prefix += pop(s);
	}
	return prefix;
}
int main()
{
	string s = "6+5*3*(2+4)*4";
	string prefix = infixToSuffix(s);
	cout << prefix << endl;
	int res = computeSuffix(prefix);
		cout << res << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值