栈(stack):是允许在一端进行插入或者删除的线性表。栈是一种线性表。只是限定了条件为在一端进行操作。
栈顶(TOP):是栈在操作那一段的第一个元素,为图中的a5
栈底(Bottom):栈的最低部,是最后一个弹出的元素,为a1,图中情况中,a1一定是最后一个弹出的。
空栈(Empty):没有任何元素存储的栈就是空栈,上图弹出a1后不压入任何元素,就成了空栈。
栈是后进先出的顺序表 因为栈顶是一直是后进的,优先弹出。
采用顺序结构存储的栈称为顺序栈。栈的主要操作时压栈和出栈,需要频繁对尾部进行增删。那么就不方便采用链式结构了,因为链式结构删除队尾的效率是很低的。所以数组来实现栈。数组在队尾增删的效率是比较可观的。栈结构体设置了三个属性
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
a用来存储元素的一位数组,_top指向栈顶元素的下一位,也是元素的个数。_capacity用来控制一维数组容量
空栈
栈不为空
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackD
void StackInit(Stack* ps) {
assert(ps);
ps->_a = NULL;
ps->_top = 0;
ps->_capacity = 0;
}
将结构体的属性设置为默认值(NULL或0)
void StackPush(Stack* ps, STDataType data) {
assert(ps);
if (ps->_top == ps->_capacity)
{
int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
STDataType* st = realloc(ps->_a, sizeof(STDataType) * newCapacity);
if (st == NULL)
{
perror("realloc fail");
return;
}
ps->_a = st;
ps->_capacity = newCapacity;
}
ps->_a[ps->_top++] = data;
}
在添加栈元素前检查存储栈元素的顺序表的空间是否满足,如果不满足则进行扩容,在返回一个新的顺序表。
void StackPop(Stack* ps) {
assert(ps&&ps->_a&&ps->_top);
ps->_top--;
}
如果栈不为空直接返回栈顶位置-1,下次添加元素的时候会覆盖这个位置。查询元素访问不到这个元素。
STDataType StackTop(Stack* ps) {
assert(ps&&ps->_top);
return ps->_a[ps->_top - 1];
}
因为top指针指向的是栈顶元素的下一个,所以要返回top-1位置的元素。
int StackEmpty(Stack* ps) {
assert(ps);
return ps->_top == 0;
}
返回元素是否为0
int StackSize(Stack* ps) {
assert(ps);
return ps->_top;
}
直接返回size
队列(queue)是只允许在一端进入,另一端删除的线性表。
队列的特点是先进先出,就像日常排队,先来的在前,先排到。
typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
typedef struct Queue
{
QNode* _front;
QNode* _rear;
int size;
}Queue;
队列的操作是入队和出队。入队是对尾进行操作,出队是对头进行操作,所以就不采用顺序结构进行存储了,因为顺序表对删除的效率太低。入队是尾插,出队是头删。可以使用链表进行存储,时间复杂度都是O(1)。队列元素的属性有存储的值和下一个节点。队列的属性有队列的头还有尾,还有队列的元素。要出队时将队列的头的指针进行改变,要入队时将队列的尾的指针的next改变,再将尾指针改变。
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
void QueueInit(Queue* q) {
q->_front = q->_rear = NULL;
q->size = 0;
}
将队列指针中的所有属性都设为默认值
void QueuePush(Queue* q, QDataType data) {
assert(q);
QNode* p = (QNode*)malloc(sizeof(QNode));
if (p == NULL)
{
perror("malloc failed");
return;
}
p->_data = data;
p->_next = NULL;
if (q->size == 0)
{
q->_front = q->_rear = p;
}
else {
q->_rear->_next = p;
q->_rear = p;
}
q->size++;
}
先申请一个新节点,将新节点的next置空。如果队列没有元素,那么加入元素后队列的头和尾就会指向同一元素。所以将头和尾都指向新节点。如果队列已经有了元素,那只需要将新节点设置rear的next,并将新节点更新尾rear。
void QueuePop(Queue* q) {
assert(q && q->size);
QNode* p = q->_front;
q->_front = q->_front->_next;
q->size--;
free(p);
}
直接将队列指针的front更新为front的next。出队必须保证队列不为空。
QDataType QueueFront(Queue* q) {
assert(q && q->size);
return q->_front->_data;
}
直接返回队列头部指针指向的值。
QDataType QueueBack(Queue* q) {
assert(q && q->size);
return q->_rear->_data;
}
直接返回队列尾部指针指向的值。
int QueueSize(Queue* q) {
assert(q );
return q->size;
}
队列结构有定义,直接返回。
int QueueEmpty(Queue* q) {
assert(q);
return q->size == 0;
}
返回队列长度是否等于0。
使用栈来实现。依次遍历字符串s的每一个字符k。如果k为左括号**“[ ( {“直接入栈,如果k为右括号”] } )”**,不匹配的情况
如果匹配的话则需要弹出栈顶元素,继续遍历s。当s遍历完后,返回栈的是否为空。(如果栈不为空,那么就有括号没有匹配,所以为false)。
typedef char STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
void StackInit(Stack* ps) {
assert(ps);
ps->_a = NULL;
ps->_top = 0;
ps->_capacity = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data) {
assert(ps);
if (ps->_top == ps->_capacity)
{
int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
Stack* st = realloc(ps->_a, sizeof(STDataType) * newCapacity);
if (st == NULL)
{
perror("realloc fail");
return;
}
ps->_a = st;
ps->_capacity=newCapacity;
}
ps->_a[ps->_top++] = data;
}
void StackPop(Stack* ps) {
assert(ps&&ps->_a&&ps->_top);
ps->_top--;
}
STDataType StackTop(Stack* ps) {
assert(ps&&ps->_top);
return ps->_a[ps->_top - 1];
}
int StackSize(Stack* ps) {
assert(ps);
return ps->_top;
}
int StackEmpty(Stack* ps) {
assert(ps);
return ps->_top == 0;
}
void StackDestroy(Stack* ps) {
assert(ps);
free(ps->_a);
ps->_capacity = 0;
ps->_top = 0;
}
bool isValid(char* s) {
Stack st;
StackInit(&st);
// if(sizeof(s)%2)return false; s是指针变量,长度固定为8
while(*s)
{
if(*s=='('||*s=='['||*s=='{')
{
StackPush(&st,*s);
} else
{
if(StackEmpty(&st)||(*s==']'&&StackTop(&st)!='[')||(*s=='}'&&StackTop(&st)!='{')||(StackTop(&st)!='('&&*s==')')){
return false;
}
StackPop(&st);
}
s++;
}
int ans = StackEmpty(&st);
StackDestroy(&st);
return ans;
}
队列的特点是先进先出,栈的特点是先进后出。可以使用两个队列。一个负责加入元素,另一个负责弹出元素。这两个队列的身份可以交换。(例如 A负责加入元素时,B就要负责元素的弹出)
typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
int size;
}Queue;
void QueueInit(Queue* q) {
q->_front = q->_rear = NULL;
q->size = 0;
}
void QueuePush(Queue* q, QDataType data) {
assert(q);
QNode* p = (QNode*)malloc(sizeof(QNode));
if (p == NULL)
{
perror("malloc failed");
return;
}
p->_data = data;
p->_next = NULL;
if (q->size == 0)
{
q->_front = q->_rear = p;
}
else {
q->_rear->_next = p;
q->_rear = p;
}
q->size++;
}
void QueuePop(Queue* q) {
assert(q && q->size);
QNode* p = q->_front;
q->_front = q->_front->_next;
q->size--;
free(p);
}
QDataType QueueFront(Queue* q) {
assert(q && q->size);
return q->_front->_data;
}
QDataType QueueBack(Queue* q) {
assert(q && q->size);
return q->_rear->_data;
}
int QueueSize(Queue* q) {
assert(q );
return q->size;
}
int QueueEmpty(Queue* q) {
assert(q);
return q->size == 0;
}
void QueueDestroy(Queue* q) {
assert(q);
while (!QueueEmpty(q))
{
QueuePop(q);
}
q->_rear = q->_front;
}
typedef struct {
Queue queue1;
Queue queue2;
} MyStack;
MyStack* myStackCreate() {
MyStack* m = ( MyStack*)malloc(sizeof(MyStack));
QueueInit(&m->queue1);
QueueInit(&m->queue2);
// printf("%d\n", &m);
return m;
}
void myStackPush(MyStack* obj, int x) {
// printf("%d\n",obj);
if(QueueEmpty(&obj->queue1))
{
QueuePush(&obj->queue2,x);
}else
{
QueuePush(&obj->queue1,x);
}
}
int myStackPop(MyStack* obj) {
Queue *queue = &obj->queue1;
Queue *nonequeue = &obj->queue2;
if(QueueEmpty(queue))
{
queue=&obj->queue2;
nonequeue=&obj->queue1;
}
QNode* rear = queue->_rear;
while(queue->size>1)
{
// printf("%d\n",1);
QueuePush(nonequeue,QueueFront(queue));
QueuePop(queue);
}
int ans = QueueFront(queue);
QueuePop(queue);
return ans;
}
int myStackTop(MyStack* obj) {
Queue *queue = &obj->queue1;
Queue *nonequeue = &obj->queue2;
if(QueueEmpty(queue))
{
queue=&obj->queue2;
nonequeue=&obj->queue1;
}
return queue->_rear->_data;
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->queue1) && QueueEmpty(&obj->queue2) ;
}
void myStackFree(MyStack* obj) {
free(obj);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/
队列时按顺序先进先出的。栈是后进先出。用栈实现的时候有两种思路
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity; // 容量
}Stack;
void StackInit(Stack* ps) {
assert(ps);
ps->_a = NULL;
ps->_top = 0;
ps->_capacity = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data) {
assert(ps);
if (ps->_top == ps->_capacity)
{
int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
STDataType* st = realloc(ps->_a, sizeof(STDataType) * newCapacity);
if (st == NULL)
{
perror("realloc fail");
return;
}
ps->_a = st;
ps->_capacity = newCapacity;
}
ps->_a[ps->_top++] = data;
}
void StackPop(Stack* ps) {
assert(ps&&ps->_a&&ps->_top);
ps->_top--;
}
STDataType StackTop(Stack* ps) {
assert(ps&&ps->_top);
return ps->_a[ps->_top - 1];
}
int StackSize(Stack* ps) {
assert(ps);
return ps->_top;
}
int StackEmpty(Stack* ps) {
assert(ps);
return ps->_top == 0;
}
void StackDestroy(Stack* ps) {
assert(ps);
free(ps->_a);
ps->_a = NULL;
ps->_capacity = 0;
ps->_top = 0;
}
typedef struct {
Stack* in;
Stack* out;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue *m = (MyQueue*)malloc(sizeof(MyQueue));
m->in =(Stack*) malloc(sizeof(Stack));
m->out =(Stack*) malloc(sizeof(Stack));
StackInit(m->in);
StackInit(m->out);
return m;
}
void myQueuePush(MyQueue* obj, int x) {
StackPush(obj->in,x);
}
int myQueuePop(MyQueue* obj) {
if(StackEmpty(obj->out))
{
while(!StackEmpty(obj->in))
{
StackPush(obj->out,StackTop(obj->in));
StackPop(obj->in);
}
}
int ans = StackTop(obj->out);
StackPop(obj->out);
return ans;
}
int myQueuePeek(MyQueue* obj) {
if(StackEmpty(obj->out))
{
while(!StackEmpty(obj->in))
{
StackPush(obj->out,StackTop(obj->in));
StackPop(obj->in);
}
}
return StackTop(obj->out);
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(obj->in) && StackEmpty(obj->out);
}
void myQueueFree(MyQueue* obj) {
StackDestroy(obj->in);
StackDestroy(obj->out);
free(obj);
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/