Author: LuoYang
Dream: 成为全栈工程师
Motto : 永远相信美好的事情即将发生。
前言
栈、队列在实际运用中可能不是特别广泛,但是队列在操作系统中应用的比较多,比如进程调度的调度队列,等待CPU的时间片,或者在12306中如果大量用户同时请求的处理方式,偶尔在算法的题目中能够看见:括号匹配、图的非递归遍历等等。
一种输入输出受限的一种数据结构
一、栈
逻辑结构:只允许在一端进行插入和删除操作的线性表
存储结构:数组 链表
数据运算:出栈 和 弹栈
1.顺序栈
如上图所示:顺序栈主依据数组的存储结构,通过数组完成栈的相关操作
//数组的存储的栈需要指定容量大小
#define MAX 100
typedef int ElementType;
//定义结构类型
typedef struct stack{
ElementType data[MAX];
int length=MAX;
int size;
}stack,*StackPointer;
//结构体中 . 和 -> 中的区别为结构体和结构体指针的使用
//获取栈顶元素
bool getTopValue(StackPointer stack,ElementType data)
{
if(!(stack->size))//栈为空
return false;
data=stack->data[stack->length];
return true;
}
//弹栈
bool pop(StackPointer stack, ElementType data)
{
if(!(stack->size))//栈为空
return false;
data=stack.data[stack->length];
stack->length--;
return true;
}
//入栈
bool push(StackPointer stack, ElementType data)
{
if(stack->length==stack->size)
return false;//栈满
stack->data[++stack->length]=data;
return true;
}
2.链栈
实际上就是链表,只不过在尾指针的排列方式不同
入栈和出栈类似于链表中的头插法的操作
如图所示:相当于链表的操作
//实际情况不变,类似链表中的头插法
//结构定义类型
typedef struct node
{
ElementType data;
NodePointer next;
}node,*NodePoninter;
typedef struct Stack_list
{
NodePointer top;
int length;
}Stack_list,*Stack_listPointer;
//弹栈和出栈的核心操作
bool founction(Stack_listPointer stack,ElementType data)
{
if(stack->length==0)return false;
//入栈操作
NodePointer node=(NodePointer)malloc(sizeof(node));
if(!node)return false;
node->data=data;
node->next=top;
top=node;
stack.length++;
//弹栈操作
NodePointer temp;
temp=top;
stack->top=stack->top.next;
*data=temp.data;
free(temp);
stack->length--;
}
3.共享栈
普通栈的缺点:每次需要固定某个内存范围大小,扩容不便
共享栈的解决方式:增加空间的利用率,但是存储空间是所需要的时间并不会减少,且只有在两栈容量满的时候,才会出现上溢的情况
代码定义如下:
//数据结构类型定义类型
typedef struct
{
ElementType data[MAx];
int top1;//0
int top2;//size
}DualStack,*DualStackPointer;
//入栈
bool push(DualStackPointer D,ElementType data,int stackChioce)
{
if(D->top1+1=D->top2)
return false;
if(stackChioce==1)
{
D->data[++D->top1]=data;
}
if(stackChioce==2)
D->data[--D->top2]=data;
return true
}
//弹栈
bool pop(DualStackPointer D,ElementType data,int stackChioce)
{
if(stackChioce==1)
{
if(D->top1==0)return false;
data=D->data[D->top1++];
}
if(stackChioce==2)
{
if(D->top2==MAX)return false;
data=D->data[D->top2--];
}
return OK
}
4.栈队列的实际运用
案例一:
.给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
3.每个右括号都有一个对应的相同类型的左括号。
//解题方法
char getCharValue(const char * value)
{
if(value=='}')return '{';
if(value==')')return '(';
if(value==']')return '[';
return 0;
}
bool isValid(char * s)
{
int length=strlen(s);
if(length%2==1)return false;
const stack[length];
int top=0;//栈顶指针,定位从0开始
char temp=0;
for(int a=0;a<length;a++)
{
temp=getCharValue(s[a]);
if(temp)
{
if(top==0&&temp!=stack[top-1])return false;//做匹配比较
top--;//弹栈
}
stack[top++]=s[a];
}
return top==0;
}
案例二,波兰式求值
波兰式(前缀表达式)逆波兰式(后缀表达式)普通表达式(中缀表达式)
前缀表达式求值
bool isNum(const char *s)
{
return ('9'>=s&&s<='0');
}
int getValue(const char *s)
{
int a=0;
char tmep=0;
int length=strlen(s);
int top=0;
const char stack[length];
for(int a=0;a<length;a++)
{
if(top>2&&isNum(s[a])&&isNum(stack[top-1]))
{
temp=stack[top-1]操作符stack[top-2]操作符s[a];
top-=2;
stack[top++]=temp;
}
stack[top++]=s[a];
}
return stack[top--];
}