用队列实现栈+用栈实现队列+循环队列(oj题)

1.题目:

力扣https://leetcode.cn/problems/implement-stack-using-queues/

思路:

核心思路:
1、入数据,往不为空的队列入、保持另一个队列为空
2、出数据的时候,依次出队头的数据,转移另一个队列保存。只剩最后一个事,Pop掉


typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;

typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;// QueueNode* cur =NULL
	while (cur != NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
}
QueueNode* BuyQueueNode(QDataType x)
{
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = BuyQueueNode(x);
	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}
void QueuePrint(Queue* pq)
{
	QueueNode* cur = pq->head;
	while (cur)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");

}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}
void QueuePop(Queue* pq)
{
	assert(pq);
	//if (pq->head == NULL)
	//	return;
	assert(!QueueEmpty(pq));

	QueueNode* next = pq->head->next;
	free(pq->head);
	pq->head = next;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
}

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;
}

int QueueSize(Queue* pq)
{
	assert(pq);

	int n = 0;
	QueueNode* cur = pq->head;
	while (cur)
	{
		++n;
		cur = cur->next;
	}

	return n;
}


//以上为队列的基本功能,下面才是解题主体部分






typedef struct 
{
    Queue q1;//第一个队列
    Queue q2;//第二个队列
} MyStack;


MyStack* myStackCreate() 
{
    MyStack*st=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&st->q1);
    QueueInit(&st->q2);
    return st;
}

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*nonemptyQ=&obj->q2;//非空队列
    if(!QueueEmpty(&obj->q1))
    {
        emptyQ=&obj->q2;
        nonemptyQ=&obj->q1;
    }

    while(QueueSize(nonemptyQ)>1)
    {
        QueuePush(emptyQ,QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }//非空队列的数据放入空队列中,只留下一个数据
    int top=QueueFront(nonemptyQ);
    QueuePop(nonemptyQ);
    return top;

}

int myStackTop(MyStack* obj) 
{
     //获取非空队列的队尾数据
  if (!QueueEmpty(&obj->q1))
  {
    return QueueBack(&obj->q1);
  }
  else
  {
    return QueueBack(&obj->q2);
  }
}

bool myStackEmpty(MyStack* obj) 
{
    //两个队列均为空,则MyStack为空
  return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) 
{
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    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);
*/

 2.题目

力扣https://leetcode.cn/problems/implement-queue-using-stacks/思路:

创建两个栈,一个栈插入数据pushST,另一个栈删除数据popST。

  • 当要插入数据时,往pushST插就行
  • 当要删除数据时,满足先进先出的条件.可以把pushST的数据放到popST,然后再把popST数据输出就可以了

用队列实现栈+用栈实现队列+循环队列(oj题)_第1张图片  

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);



void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0; // ps->top = -1;
	ps->capacity = 0;
}

void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

void StackPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = realloc(ps->a, sizeof(STDataType)*newCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->a[ps->top - 1];
}

int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return ps->top == 0;
}

//以上代码是栈的基本功能实现,以下代码是解题主体部分




typedef struct 
{
    ST pushST;//插入数据的栈
    ST popST;//删除数据的栈
} MyQueue;


MyQueue* myQueueCreate() 
{
    MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&obj->pushST);//插入数据的栈的初始化
    StackInit(&obj->popST);//删除数据的栈的初始化
    return obj;
}

void myQueuePush(MyQueue* obj, int x) 
{
    StackPush(&obj->pushST,x);//插入数据
}

bool myQueueEmpty(MyQueue* obj) 
{
     return StackEmpty(&obj->pushST)&&StackEmpty(&obj->popST);//两个栈均为空,则“队列”为空
}

int myQueuePeek(MyQueue* obj) 
{
    // 如果popST中没有数据,将pushST的数据导过去
    // popST中的数据就符合先进先出的顺序了
     if(StackEmpty(&obj->popST))//popST为空时,需先将pushST中数据导入popST
    {
        while(!StackEmpty(&obj->pushST))//将pushST数据全部导入popST
        {
            StackPush(&obj->popST, StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }
    return StackTop(&obj->popST);//返回popST栈顶的元素

}

int myQueuePop(MyQueue* obj) 
{
    // 如果popST中没有数据,将pushsT的数据导过去
    // popST中的数据就符合先进先出的顺序了
    int top=myQueuePeek(obj);
    StackPop(&obj->popST);//删除数据
    return top;
}



void myQueueFree(MyQueue* obj) 
{
    //先释放两个栈,再释放队列的结构体类型
    StackDestroy(&obj->pushST);
    StackDestroy(&obj->popST);
    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);
*/

 3.题目

力扣https://leetcode.cn/problems/design-circular-queue/用队列实现栈+用栈实现队列+循环队列(oj题)_第2张图片

循环队列的特点:

  • 1、符合先进先出
  • 2、空间大小是固定

重点:循环队列,无论使用数组实现还是链表实现,都要多开一个空间,也就意味着,要是一个存k个数据的循环队列,要开k+1个空间否则无法实现判空和判满。

#define _CRT_SECURE_NO_WARNINGS 1
#include 
#include 
#include 

typedef struct
{
	int* a;//数组
	int front;//队头
	int tail;//队尾
	int k;//队列存储的数据
}MyCircularQueue;

//构造器,设置队列长度为 k 。
MyCircularQueue* myCircularQueueCreate(int k)
{
	MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//申请一个环形队列
	cq->a = (int*)malloc(sizeof(int) * (k + 1));//开辟队列空间
	cq -> front = cq->tail = 0;//队头队尾都为0,此时空队列
	cq->k = k;//存储的有效数据

	return cq;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
// 向循环队列插入一个元素。如果成功插入则返回真。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
	if (myCircularQueueIsFull(obj))
		return false;

	obj->a[obj->tail] = value;
	++obj->tail;
	obj->tail %= (obj->k + 1);//使队列循环

	return true;
}

//从循环队列中删除一个元素。如果成功删除则返回真。
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return false;

	++obj->front;
	obj->front %= (obj->k + 1);//使队列循环
	return true;
}

//获取队首元素
int myCircularQueueFront(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return -1;
	return obj->a[obj->front];
}

//获取队尾元素
int myCircularQueueRear(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
		return -1;

	int i = (obj->tail + obj->k) % (obj->k + 1);
		return obj->a[i];
}


//循环队列释放
void myCircularQueueFree(MyCircularQueue* obj)
{
	free(obj->a);
	free(obj);
}

//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
	return obj->front == obj->tail;
}

//检查循环队列是否已满。
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
	return (obj->tail + 1) % (obj->k + 1) == obj->front;
}




void Test() 
{
	MyCircularQueue* obj = myCircularQueueCreate(3);
	myCircularQueueEnQueue(obj, 1);
	myCircularQueueEnQueue(obj, 2);
	myCircularQueueEnQueue(obj, 3);
	myCircularQueueEnQueue(obj, 4);//队满

	printf("front=%d\n", myCircularQueueFront(obj));//获取队头1
	printf("rear=%d\n", myCircularQueueRear(obj));//获取队尾3

	myCircularQueueDeQueue(obj);//出队1
	printf("front=%d\n", myCircularQueueFront(obj));//获取队头2

	myCircularQueueFree(obj);//销毁
}

int main()
{
	Test();
	return 0;
}

你可能感兴趣的:(数据结构刷题,数据结构)