1.用两个队列模拟一个栈
分析:栈是后进先出的,队列是先进先出的。要想实现栈,就需要将最后进队列的元素先出,则只需要一个队列为空,一个队列用来接受元素。当要进栈的时候,要将元素插入到一个非空的队列中,保持另一个是空队列;当要出栈的时候,将非空队列的元素逐步出到另一个空队列中,当非空队列只有一个元素的时候,将此时的元素出队列,并且不在入另一个队列,此时的元素就是出栈的元素。
【相关函数的实现】
typedef int QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
typedef struct {
Queue q1;
Queue q2;
} MyStack;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* p = pq->head;
QNode* q = NULL;
while (p)
{
q = p->next;
free(p);
p = q;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDatatype x)
{
assert(pq);
QNode* s = (QNode*)malloc(sizeof(QNode));
if (s == NULL)
{
perror("malloc fail");
return;
}
s->data = x;
s->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = s;
}
else
{
pq->tail->next = s;
pq->tail = s;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
QNode* p = pq->head;
if (pq->head == pq->tail)
{
pq->head = pq->head->next;
pq->tail = pq->head;
}
else
{
pq->head = pq->head->next;
}
free(p);
pq->size--;
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return !(pq->size);
}
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if (obj == NULL)
{
perror("malloc fail");
return NULL;
}
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
assert(obj);
if (!(QueueEmpty(&obj->q1)))
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
int myStackPop(MyStack* obj) {
assert(obj);
Queue* empty = &obj->q1;
Queue* nonempty = &obj->q2;
if (!(QueueEmpty(&obj->q1)))
{
empty = &obj->q2;
nonempty = &obj->q1;
}
while (nonempty->size > 1)
{
int tmp = QueueFront(nonempty);
QueuePush(empty, tmp);
QueuePop(nonempty);
}
int top = QueueFront(nonempty);
QueuePop(nonempty);
return top;
}
int myStackTop(MyStack* obj) {
assert(obj);
if (!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
assert(obj);
if (QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2))
{
return 1;
}
else
return 0;
}
void myStackFree(MyStack* obj) {
assert(obj);
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
2.用两个栈来实现队列的操作
分析:栈是后进先出的,队列是先进先出的。进栈会将原来的顺序逆置,则只需要进两次栈就可以保持原来的顺序不变。进队列的时候,将元素进入进栈的栈中;出队列的时候,将出出栈中元素,当出栈的位空的时候,在将进栈的元素全部进到出栈中,此时在出出栈中的元素。
【函数实现】
typedef int SElemType;
typedef struct snode
{
SElemType data;
struct snode* next;
}SNode,*LinkStack;
typedef struct
{
LinkStack push_stack;
LinkStack pop_stack;
} MyQueue;
void destroy_LinkStack(LinkStack* LS);
void init_LinkStack(LinkStack* LS);
int empty_LinkStack(LinkStack S);
int get_top_LinkStack(LinkStack S, SElemType* e);
int LengthLinkStack(LinkStack S);
int push_LinkStack(LinkStack* LS, SElemType x);
int pop_LinkStack(LinkStack* LS, SElemType* e);
//链栈的初始化
void init_LinkStack(LinkStack* LS)
{
assert(LS);
*LS = NULL;
}
//判断是否栈空
int empty_LinkStack(LinkStack S)
{
//assert(S);
if (S == NULL)return 1;
else return 0;
}
//获取栈顶元素
int get_top_LinkStack(LinkStack S, SElemType* e)
{
assert(S);
*e = S->data;
return 1;
}
//求栈的长度
int LengthLinkStack(LinkStack S)
{
int n = 0;
LinkStack p = S;
while (p)
{
n++;
p = p->next;
}
return n;
}
//链栈的进栈操作
int push_LinkStack(LinkStack* LS, SElemType x)
{
LinkStack s = (LinkStack)malloc(sizeof(SNode));
if (s == NULL)
{
perror("malloc fail");
return 0;
}
s->data = x;
s->next = NULL;
if (*LS == NULL)
{
*LS = s;
}
else
{
s->next = (*LS)->next;
(*LS)->next = s;
}
return 1;
}
//链栈的出栈操作
int pop_LinkStack(LinkStack* LS, SElemType* e)
{
assert(!empty_LinkStack(*LS));
LinkStack p = *LS;
*LS = (*LS)->next;
*e = p->data;
free(p);
return 1;
}
//链栈的销毁操作
void destroy_LinkStack(LinkStack* LS)
{
LinkStack p = *LS;
LinkStack q = NULL;
while (p)
{
q = p->next;
free(p);
p = q;
}
*LS = NULL;
}
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("malloc fail");
return NULL;
}
init_LinkStack(&obj->push_stack);
init_LinkStack(&obj->pop_stack);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
push_LinkStack(&obj->push_stack,x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
if(empty_LinkStack(obj->pop_stack))
{
while(!empty_LinkStack(obj->push_stack))
{
SElemType e=0;
get_top_LinkStack(obj->push_stack,&e);
push_LinkStack(&obj->pop_stack,e);
pop_LinkStack(&obj->push_stack,&e);
}
}
SElemType top=0;
pop_LinkStack(&obj->pop_stack,&top);
return top;
}
int myQueuePeek(MyQueue* obj) {
assert(obj);
if(empty_LinkStack(obj->pop_stack))
{
while(!empty_LinkStack(obj->push_stack))
{
SElemType e=0;
get_top_LinkStack(obj->push_stack,&e);
push_LinkStack(&obj->pop_stack,e);
pop_LinkStack(&obj->push_stack,&e);
}
}
SElemType top=0;
get_top_LinkStack(obj->pop_stack,&top);
return top;
}
bool myQueueEmpty(MyQueue* obj) {
assert(obj);
return empty_LinkStack(obj->push_stack)&&empty_LinkStack(obj->pop_stack) ;
}
void myQueueFree(MyQueue* obj) {
assert(obj);
destroy_LinkStack(&obj->pop_stack);
destroy_LinkStack(&obj->push_stack);
free(obj);
}
3.循环队列
分析:循环队里的特点是提前知道需要多大的空间,并提前开辟好空间。此时关键是要判断什么时候是空队列,什么时候是满队列,为了方便判断,在开辟空间的时候需要多开辟一块空间。因为是提前知道需要多少空间,开辟数组会比链式结构简单。此时设置队头和队尾的参数,队头指向的队头的元素,队尾指向的队尾元素的下一个位置。再设置一个循环队列的长度,用于方便取模来表示循环。注意:在队头队尾相加减的时候要注意取模。
【函数实现】
typedef struct {
int*a;
int front;
int rear;
int size_queue;
} MyCircularQueue;
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
if(obj==NULL)
{
perror("malloc fail");
return NULL;
}
obj->a=(int *)malloc((k+1)*sizeof(int));
if(obj->a==NULL)
{
perror("malloc fail");
return NULL;
}
obj->front=obj->rear=0;
obj->size_queue=k+1;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->rear]=value;
obj->rear=(obj->rear+1)%obj->size_queue;
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return false;
obj->front=(obj->front+1+obj->size_queue)%obj->size_queue;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
else
{
int rear=(obj->rear-1+obj->size_queue)%obj->size_queue;
return obj->a[rear];
}
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
if(obj->front==obj->rear)
{
return true;
}
else
{
return false;
}
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
if((obj->rear+1)%obj->size_queue==obj->front)
return true;
else
return false;
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}