目录
栈与队列
栈是一种“FILO”(先进后出)的数据结构
队列是一种“FIFO”(先进先出)的数据结构
有了以上信息后,我们就可以实现用栈来实现队列&用队列实现栈的操作了
两个栈实现一个队列结构
由于队列是先入先出的结构,而栈是先入后出的结构。
所以我们选择用两个栈,来使数据形成一个翻转
这样翻转后的结构,便可以轻松用pop出掉最先进来的元素。
当stack2中的元素pop完时,我们就再进行一个翻转,将所有压进stack1的元素再次翻转到stack2中,便又可以进行出栈了。
所以我们就需要一个变量来判断栈是否为空。以下在定义结构体时,增加了一个整形size变量,来记录栈内的元素个数。
而push就是正常的入栈,一个劲往stack1中入就行。
如下是代码实现
typedef struct Stack{
struct Stack*next;
struct Stack*tail;
int size;//这里设置size来判断该栈是否为空
int data;
}MyStack;
typedef struct {
MyStack*q1;
MyStack*q2;
}MyQueue;
/*创建队列*/
MyQueue* myQueueCreate() {
MyQueue*Queue=(MyQueue*)malloc(sizeof(MyQueue));
Queue->q1=(MyStack*)malloc(sizeof(MyStack));//创建哨兵位
Queue->q2=(MyStack*)malloc(sizeof(MyStack));
Queue->q1->next=NULL;//初始化栈
Queue->q2->next=NULL;
Queue->q1->tail=NULL;
Queue->q2->tail=NULL;
Queue->q1->size=0;
Queue->q2->size=0;
Queue->q1->data=0;
Queue->q2->data=0;
return Queue;
}
/*尾插队列*/
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
MyStack*newnode=(MyStack*)malloc(sizeof(MyStack));//开辟新结点
newnode->data=x;
newnode->next=NULL;
MyStack*cur=obj->q1->size==0?obj->q1:obj->q1->tail;
obj->q1->tail=newnode;//链接新结点
cur->next=obj->q1->tail;
obj->q1->size++;
}
void StackMove(MyStack*sorc,MyStack*dest){
while(sorc->size)
{
MyStack*curq1=sorc;
MyStack*curq2=dest;
while(curq1->next!=sorc->tail)
{
curq1=curq1->next;
}
curq1->next=NULL;
curq2=dest->size==0?dest:dest->tail;
dest->tail=sorc->tail;
curq2->next=dest->tail;
dest->size++;
sorc->tail=curq1;
sorc->size--;
}
}
/*头删队列*/
int myQueuePop(MyQueue* obj) {
assert(obj);
assert(obj->q1->size || obj->q2->size);
if(obj->q2->size==0)
{
StackMove(obj->q1,obj->q2);
}
MyStack*cur=obj->q2;
while(cur->next!=obj->q2->tail)
{
cur=cur->next;
}
int ret=obj->q2->tail->data;
free(obj->q2->tail);
cur->next=NULL;
obj->q2->tail=cur;
obj->q2->size--;
return ret;
}
/*返回队列开头元素*/
int myQueuePeek(MyQueue* obj) {
assert(obj);
assert(obj->q1->size || obj->q2->size);
if(obj->q2->size==0)
{
return obj->q1->next->data;
}
else
return obj->q2->tail->data;
}
/*判空*/
bool myQueueEmpty(MyQueue* obj) {
if(obj->q1->size || obj->q2->size)
{
return false;
}
return true;
}
/*释放空间*/
void myQueueFree(MyQueue* obj) {
assert(obj);
StackMove(obj->q1,obj->q2);
free(obj->q1);
MyStack*cur=obj->q2->next;
MyStack*node=obj->q2->next;
while(cur)
{
cur=cur->next;
free(node);
node=cur;
obj->q2->size--;
}
free(obj->q2);
free(obj);
}
两个队列实现一个栈结构
我们选用两个队列,实现一个”无用数据”的”转移“ 。
我们有两个队列,一个空,一个非空。
出队列:将非空队列的n-1个元素入到空队列中,剩下一个没有移动的元素直接从原队列头删。
入队列:只向非空队列入数据
因此,实现该功能的核心内容是判断空与非空队列并进行元素转移
实现代码如下:
typedef struct Queue
{
struct Queue*next;
int data;
int size;
}Queue;
typedef struct {
Queue*q1;
Queue*q2;
} MyStack;
/*创建结构体*/
MyStack* myStackCreate() {
MyStack*Stack=(MyStack*)malloc(sizeof(MyStack));//开辟含有两个队列的结构体
Stack->q1=(Queue*)malloc(sizeof(Queue));//开辟第一个结构体,并初始化,附加哨兵位
Stack->q1->next=NULL;
Stack->q1->data=0;
Stack->q1->size=0;
Stack->q2=(Queue*)malloc(sizeof(Queue));//开辟第二个结构体,并初始化,附加哨兵位
Stack->q2->next=NULL;
Stack->q2->data=0;
Stack->q2->size=0;
return Stack;//返回开辟含有队列的结构体的指针
}
/*存放数据*/
void myStackPush(MyStack* obj, int x) {
assert(obj); //判断stack是否为空
Queue* newnode=(Queue*)malloc(sizeof(Queue));//创建要尾插的新结点,并赋值该结点
newnode->data=x;
newnode->next=NULL;
Queue* notemptynode=NULL;//判断q1,q2哪个是非空链表,若都为空则默认q1
if(obj->q2->size!=0)
{
notemptynode=obj->q2;
}
else
{
notemptynode=obj->q1;
}
Queue*cur=notemptynode;
while(cur->next)//找尾
{
cur=cur->next;
}
cur->next=newnode;//链接尾结点和新结点
notemptynode->size++;
}
/*将第一个队列的值转移到第二个队列中*/
void myStackMove(Queue*notemptynode,Queue*emptynode,int count)
{
if(notemptynode->size!=1)
{
emptynode->next=notemptynode->next;
}
Queue*cur=notemptynode->next;
Queue*tailnode=notemptynode->next;
while(--count)//留下一个值,用来pop; 找尾
{
cur=tailnode;
tailnode=tailnode->next;
notemptynode->size--;
emptynode->size++;
}
notemptynode->size--;
notemptynode->next=tailnode;
cur->next=NULL;
}
/*出队列*/
int myStackPop(MyStack* obj) {
assert(obj->q1->next||obj->q2->next);
Queue*emptynode=obj->q2;
Queue*notemptynode=obj->q1;
if(obj->q1->size==0)//判断谁是空队列
{
emptynode=obj->q1;
notemptynode=obj->q2;
}
int count=notemptynode->size;//计算非空队列长度,用来下一步转移数据
myStackMove(notemptynode,emptynode,count); //转移队列数据,留下一个用来pop
int cur=notemptynode->next->data;//保存要pop的结点的值
free(notemptynode->next);//释放pop的结点
notemptynode->next=NULL;
return cur;
}
/*返回栈顶元素*/
int myStackTop(MyStack* obj) {
assert(obj->q1->size||obj->q2->size);//确保两个队列其中一个有数据
Queue*cur=NULL;
if(obj->q1->size!=0)
{
cur=obj->q1;
while(cur->next)
{
cur=cur->next;
}
}
else
{
cur=obj->q2;
while(cur->next)
{
cur=cur->next;
}
}
return cur->data;
}
/*判断两队列是否都为空*/
bool myStackEmpty(MyStack* obj) {
if(obj->q1->size==0 && obj->q2->size==0)
{
return true;
}
else
return false;
}
/*释放内存*/
void myStackFree(MyStack* obj) {
assert(obj);
Queue*cur1=obj->q1;
Queue*cur2=obj->q2;
while(cur1)
{
cur1=cur1->next;
free(obj->q1);
obj->q1=cur1;
}
while(cur2)
{
cur2=cur2->next;
free(obj->q2);
obj->q2=cur2;
}
}