(数据结构)顺序栈操作——C实现(部分C++)

特点
1.先进后出
2.分为顺序栈和链栈
3.对于链栈来说
使用头插头删法:(建议使用这种方式
栈顶就是头结点,没有栈底(NULL)
使用尾插尾删法:
栈底就是头结点,栈顶:重新定义一个指针指向最后一个结点
删除得从头结点开始找到当前栈顶的前驱结点O(n)

顺序栈的结构设计

typedef struct Stack
{
	ElemType  *elem;   //栈空间的首地址或栈底指针
	int               top;//下标,栈顶指针
	int               stacksize;//当前栈空间的大小
}SqStack,*PStack;  

其他参数

#define STACK_ININ_SIZE   10           //栈空间初始大小
#define STACKINCREMENT  5           //栈空间增量

typedef int ElemType;

顺序栈操作

初始化

void InitStack(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("InitStack : : 栈无效\n");
		exit(0);
	}

	st->elem = (ElemType*)malloc(STACK_ININ_SIZE * sizeof(ElemType));
	if(st->elem == NULL)
	{
		printf("InitStack : : 空间申请失败!\n");
		exit(0);
	}

     st->top = 0;
	 st->stacksize = STACK_ININ_SIZE;
}

判满

int IsEmpty(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("IsEmpty: : 栈无效\n");
		exit(0);
	}

	return st->top == 0;
}

扩容

static void AppendStack(PStack st)
{
	if(st->stacksize == 0)
	{
		InitStack(st);
		return;
	}
	ElemType *s = (ElemType *)malloc((st->stacksize + STACKINCREMENT) * sizeof(ElemType));
	if(s == NULL)
	{
		return;
	}

	for(int i = 0;i < st->top;i++ )
	{
		  s[i] = st->elem[i];
	}

	free(st->elem);
	st->elem = s;
	st->stacksize += STACKINCREMENT;
}

入栈

void Push(PStack st,ElemType val)
{
    /*
		1.是否为有效栈
		2.判满,是否需要扩容
		3.将val入栈
	*/

	assert(st != NULL);
	if(st == NULL)
	{
		printf("Push : : 栈无效\n");
		exit(0);
	}

	if(st->top == st->stacksize)
	{
		AppendStack(st);
	}

	st->elem[st->top++] = val;
}

出栈

void Pop(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("Pop: : 栈无效\n");
		exit(0);
	}

	if(IsEmpty(st))
	{
		return;
	}

	st->top--;
}

获取栈顶元素

ElemType Top(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("Top: : 栈无效\n");
		exit(0);
	}

	return st->elem[st->top - 1];
}

获取栈内元素个数

int Size(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("Size: : 栈无效\n");
		exit(0);
	}

	return st->top ;
}

清空,只是清空栈的元素!

void ClearStack(PStack st)//只是清空栈的元素
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("ClearStack: : 栈无效\n");
		exit(0);
	}

	st->top = 0;
}

销毁,回收内存

void DestroyStack(PStack st)
{
	assert(st != NULL);
	if(st == NULL)
	{
		printf("DestroyStack: : 栈无效\n");
		exit(0);
	}

	free(st->elem);
	st->elem = NULL;
	st->stacksize = st->top = 0;
}

应用

中缀表达式转后缀表达式
在这里插入图片描述

void MidToLast(const char *str)
{
	SqStack st;
	InitStack(&st);

	char c = 0;

	const char *p = str;
	while(*p)
	{
		if(isdigit(*p))
		{
			printf("%c",*p);
			p++;
			continue;
		}
		switch(*p)
		{
		case '(':
			Push(&st,*p);
			break;

		case ')':
			while(1)
			{
				c = Top(&st);
				Pop(&st);
				if(c == '(')
				{
					break;
				}
				printf("%c",c);
			}
			

		case '*':
		case '/':
			while(!IsEmpty(&st))
			{
				c = Top(&st);
				if(c == '(' || c == '+' || c == '-')
				{
					break;
				}
				Pop(&st);
				printf("%c",c);
			}
			Push(&st,*p);
			break;
				
	
		case '+':
		case '-':
					while(!IsEmpty(&st))
			{
				c = Top(&st);
				if(c == '(' )
				{
					break;
				}
				Pop(&st);
				printf("%c",c);
			}
			Push(&st,*p);
			break;
		}
			p++;
	}

	//将栈中的剩余内容全部出栈
	while(!IsEmpty(&st))
	{
		c = Top(&st);
		Pop(&st);
		printf("%c",c);
	}

	DestroyStack(&st);
}

经典题目

两个栈实现队列

基本思想:
定义两个栈,栈st1用于实现队列的入队列操作,另外一个st2用于实现出队列和取队头元素的操作,已知对栈的操作借助已完成的对顺序栈的操作。如果做pop和peak操作,都从s2的栈顶直接操作,如果s2为空,把s1里面的元素全部倒过来。

结构设计

typedef struct Que
{
	SqStack st1;
	SqStack st2;
}StackQue;

初始化

void InitStackQue(StackQue *que)
{
	assert(que != NULL);
	if(que == NULL)
	{
		printf("StackQue Error\n");
		exit(0);
	}

	InitStack(&que->st1);
	InitStack(&que->st2);
}

判空

两个栈均为空,那么这个队列就为空

int IsEmptyStackQue(StackQue *que)
{
	assert(que != NULL);

	if(IsEmpty(&que->st1) && IsEmpty(&que->st2)) 
		return 1;
}

判满

因为在对栈操作时,已经考虑了栈满时的扩容操作,因此,栈不可能满,所以队列也不会满。

int IsFullStackQue(StackQue *que)
{
	return 0;
}

入队列

int PushStackQue(StackQue *que,ElemType val)
{
	assert(que != NULL);

	if(IsFullStackQue(que))
	{
		return 0;
	}

	Push(&que->st1,val);
	return 1;
}

出队列

基本思路:
1.当两个栈都为空时,说明这个队列为空,直接退出
2.当st1和st2均不为空时,先将st2中的元素全部弹出,在将st1中的剩余元素弹出并入到st2中,再弹出st2。
3.st1为空,st2不为空时,直接对st2做弹栈操作即可。
3.st1不为空,st2为空时,先将st2中的元素全部弹出,在将st1中的剩余元素弹出并入到st2中,再弹出st2。
4.完成上述23操作后,st2肯定非空,直接对st2做弹栈操作即可。

int PopStackQue(StackQue *que,ElemType *rtval)
{
	assert(que != NULL);

	//空队列
	if(IsEmptyStackQue(que))
	{
		return 0;
	}

	//st2为空时
	if(IsEmpty(&que->st2))
	{
		//将st1中的所有元素导到st2中
		while(!IsEmpty(&que->st1))
		{
			ElemType tmp = Top(&que->st1);
			Push(&que->st2,tmp);
			Pop(&que->st1);
		}
	}

	//接下来st2肯定非空
	*rtval = Top(&que->st2);
	Pop(&que->st2);
	return 1;
}

C++实现

class MyQueue {
public:
    MyQueue() {

    }
    
    void push(int x) {
        s1.push(x);

    }
    
    int pop() {
        if(s2.empty())
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        int val = s2.top();
        s2.pop();
        return val;
    }
    
    int peek() {
        if(s2.empty())
        {
            while(!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        return s2.top();
    }
    
    bool empty() {
        return s1.empty()&&s2.empty();

    }

private:
    stack<int> s1;
    stack<int> s2;
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值