目录
1.栈的表示和实现
1.1栈的概念及结构
个人理解:栈就相当于手枪的子弹夹,塞子弹的弹夹口就是栈顶,弹夹另一端就是栈底。先塞进去的子弹最后打出去,最后塞进弹夹的子弹第一个打
出去。正所谓后来者居上!!!LIFO(Last In First Out)
官方定义:
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除
操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)
的原则。
压栈:栈的插入操作叫做进栈
/
压栈
/
入栈,
入数据在栈顶
。
出栈:栈的删除操作叫做出栈。
出数据也在栈顶
。
1.2栈的实现
栈的实现一般可以使用
数组或者链表实现
,相对而言数组的结构实现更优一些。因为数组在尾上
插入数据的代价比较小。
1.3栈的代码
使用动态数组实现可动态增长的栈:
//动态数组实现栈的各种接口
typedef int SDataType;
typedef struct Stack
{
SDataType *a;
int capacity;
int top;
}Stack;
//初始化栈
void StackInit(Stack* ps);
//栈的销毁
void StackDestory(Stack* ps);
//内存检查,不够则自动扩容
void CheckCapacity(Stack*ps);
//进栈
void StackPush(Stack* ps, SDataType x);
//出栈
void StackPop(Stack* ps);
//判空
bool StackEmpty(Stack*ps);
//获取栈顶元素
SDataType StackTop(Stack*ps);
//计算栈中元素个数
SDataType StackSize(Stack*ps);
老规矩以下分别实现各个接口函数:
void StackInit(Stack*ps)
{
ps->a = 0;
ps->capacity = 0;
ps-> top = 0;
}
void CheckCapacity(Stack*ps)
{
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SDataType*tmp = (SDataType*)realloc(ps->a,sizeof(SDataType)*newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
void StackDestory(Stack*ps)
{
assert(ps);
free(ps->a);
ps->capacity = ps->top = 0;
ps->a= NULL;
}
void StackPush(Stack* ps,SDataType x)
{
assert(ps);
CheckCapacity(ps);
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
bool StackEmpty(Stack*ps)
{
assert(ps);
return ps->top==0;
}
SDataType StackTop(Stack*ps)
{
assert(ps);
assert(ps -> top > 0);
return ps->a[ps->top-1];
}
SDataType StackSize(Stack*ps)
{
assert(ps);
return ps->top;
}
2.队列的表示和实现
2.1队列的概念及结构
个人理解:字面意思,队列就是我们日常生活中排队的队列,谁先排入队列中的先轮到谁。
FIFO(First In First Out) 严格按照这一规律,不能插队!不同的是还不能在排队中途退出排队!hh 是不是很坑!
官方定义:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先
进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为
队尾
出队列:进行删除操作的一
端称为
队头
2.2队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,
出队列在数组头上出数据,效率会比较低。
此处采用无头不循环单链表实现
2.3队列代码
//单链表实现队列
//链式结构表示队列
typedef int SDataType;
typedef struct QueueNode
{
SDataType data;
struct QueueNode* next;
}QNode;
//队列的结构
typedef struct Queue
{
QNode* head; //指向队头的指针
QNode* tail; //指向队尾的指针
}Queue;
//队列的初始化
void QueueInit(Queue*pq);
//销毁
void QueueDestroy(Queue*pq)
//队尾入
void QueuePush(Queue*pq,SDataType x);
//队头出
void QueuePop(Queue*pq);
//获取队头元素
SDataType QueueFront(Queue*pq);
//获取队尾元素
SDataType QueueBack(Queue*pq);
//判空
bool QueueEmpty(Queue*pq);
//元素个数
int QueueSize(Queue*pq);
老规矩 以下分别实现上述各个接口函数:
void QueueInit(Queue*pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestroy(Queue*pq)
{
assert(pq);
QNode *val = pq->head;
while (pq->head != NULL)
{
pq->head=pq->head->next;
free(val);
}
}
void QueuePush(Queue*pq,SDataType x)//队尾入
{
assert(pq);
QNode*newnode = (QNode*)malloc(sizeof(QNode));
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = pq->tail->next;
}
}
void QueuePop(Queue*pq) //队头出
{
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode*next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
SDataType QueueFront(Queue*pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
SDataType QueueBack(Queue*pq)
{
assert(pq);
assert(pq->head);
return pq->tail->data;
}
bool QueueEmpty(Queue*pq)
{
assert(pq);
return pq->head == NULL;
}
int QueueSize(Queue*pq)
{
QNode*cur = pq->head;
int size = 0;
while (cur != 0)
{
cur = cur->next;
size++;
}
return size;
}
3.终极队列和栈的OJ题
3.1 括号匹配问题。
解答如下:
typedef char SDataType;
typedef struct Stack
{
SDataType *a;
int capacity;
int top;
}Stack;
void StackInit(Stack*ps)
{
ps->a = 0;
ps->capacity = 0;
ps-> top = 0;
}
void CheckCapacity(Stack*ps)
{
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SDataType*tmp = (SDataType*)realloc(ps->a,sizeof(SDataType)*newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
void StackDestory(Stack*ps)
{
assert(ps);
free(ps->a);
ps->capacity = ps->top = 0;
ps->a= NULL;
}
void StackPush(Stack* ps,SDataType x)
{
assert(ps);
CheckCapacity(ps);
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
bool StackEmpty(Stack*ps)
{
assert(ps);
return ps->top==0;
}
SDataType StackTop(Stack*ps)
{
assert(ps);
assert(ps -> top > 0);
return ps->a[ps->top-1];
}
SDataType StackSize(Stack*ps)
{
assert(ps);
return ps->top;
}
bool isValid(char * s)
{
Stack st;
StackInit(&st);
while(*s!='\0')
{
switch(*s)
{
case'{':
case'(':
case'[':
{
StackPush(&st,*s);
*s++;
break;
}
case '}':
case ')':
case ']':
{
if(StackEmpty(&st))
{
StackDestory(&st);
return false;
}
char top=StackTop(&st);
StackPop(&st);
if((top=='{' && *s !='}')
||(top=='(' && *s !=')')
||(top=='[' && *s !=']'))
{
StackDestory(&st);
return false;
}
else
{
*s++;
}
break;
}
}
}
bool ret=StackEmpty(&st);
return ret;
StackDestory(&st);
}
3.2 用队列实现栈。
typedef int QDataType;
typedef struct QueueNode //单链表实现队列
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
// 队尾入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
// 队头出
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head);
// 1、一个
// 2、多个
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->tail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
int size = 0;
QNode* cur = pq->head;
while (cur)
{
++size;
cur = cur->next;
}
return size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head==NULL ; //条件成立 返回true 不成立返回false
}
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate()
{
MyStack*ps=(MyStack*)malloc(sizeof(MyStack));
if(ps==NULL)
{
exit(-1);
}
QueueInit(&ps->q1);
QueueInit(&ps->q2);
return ps;
}
void myStackPush(MyStack* obj, int x)
{
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj)
{
Queue*emptyQ=&obj->q1;
Queue*noemptyQ=&obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ=&obj->q2;
noemptyQ=&obj->q1;
}
while(QueueSize(noemptyQ)>1)
{
QueuePush(emptyQ,QueueFront(noemptyQ));
QueuePop(noemptyQ);
}
int top= QueueFront(noemptyQ);
QueuePop(noemptyQ);
return top;
}
int myStackTop(MyStack* obj)
{
if(!QueueEmpty(&obj->q1))
return QueueBack(&obj->q1);
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj)
{
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj)
{
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
free(obj);
}
3.3 用栈实现队列
typedef int SDataType;
typedef struct Stack
{
SDataType *a;
int capacity;
int top;
}Stack;
void StackInit(Stack*ps)
{
ps->a = 0;
ps->capacity = 0;
ps-> top = 0;
}
void CheckCapacity(Stack*ps)
{
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SDataType*tmp = (SDataType*)realloc(ps->a,sizeof(SDataType)*newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
void StackDestory(Stack*ps)
{
assert(ps);
free(ps->a);
ps->capacity = ps->top = 0;
ps->a= NULL;
}
void StackPush(Stack* ps,SDataType x)
{
assert(ps);
CheckCapacity(ps);
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
bool StackEmpty(Stack*ps)
{
assert(ps);
return ps->top==0;
}
SDataType StackTop(Stack*ps)
{
assert(ps);
assert(ps -> top > 0);
return ps->a[ps->top-1];
}
SDataType StackSize(Stack*ps)
{
assert(ps);
return ps->top;
}
typedef struct
{
Stack s1;
Stack s2;
} MyQueue;
MyQueue* myQueueCreate()
{
MyQueue*ps=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&ps->s1);
StackInit(&ps->s2);
return ps;
}
void myQueuePush(MyQueue* obj, int x)
{
StackPush(&obj->s1,x);
}
int myQueuePop(MyQueue* obj)
{
if(StackEmpty(&obj->s2))
{
while(!StackEmpty(&obj->s1))
{
StackPush(&obj->s2,StackTop(&obj->s1));
StackPop(&obj->s1);
}
}
int top=StackTop(&obj->s2);
StackPop(&obj->s2);
return top;
// int top = myQueuePeek(obj);
//StackPop(&obj->s2);
//return top;
}
int myQueuePeek(MyQueue* obj)
{
if(StackSize(&obj->s2)==0)
{
while(StackSize(&obj->s1)>0)
{
StackPush(&obj->s2,StackTop(&obj->s1));
StackPop(&obj->s1);
}
}
return StackTop(&obj->s2);
}
bool myQueueEmpty(MyQueue* obj)
{
return StackEmpty(&obj->s1) && StackEmpty(&obj->s2);
}
void myQueueFree(MyQueue* obj)
{
StackDestory(&obj->s1);
StackDestory(&obj->s2);
free(obj);
}
后面两题类似都是使用队列和栈的性质 来回操作。