栈和队列的介绍

栈的概念与结构:

一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据也在栈顶

栈的实现:

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

void StackInit(SNode* phead)
{
	assert(phead);

	STDataType* tmp= (STDataType*)malloc(sizeof(STDataType) * 4);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}

	phead->top = tmp;
	tmp = NULL;

	phead->size = 0;
	phead->capatipy = 4;
}

void StackPush(SNode* phead, STDataType x)
{
	assert(phead);

	if (phead->capatipy == phead->size)
	{
		STDataType* tmp = (STDataType*)realloc(phead->top,sizeof(STDataType) * 2*(phead->capatipy));
		if (tmp == NULL)
		{
			perror("raalloc fail");
			return;
		}

		phead->top = tmp;
		tmp == NULL;
		phead->capatipy *= 2;
	}

	phead->top[phead->size] = x;
	phead->size++;
}

void StackPop(SNode* phead)
{
	assert(phead);
	assert(!StackEmpty(phead));

	phead->size--;
}

void StackDestroy(SNode* phead)
{
	assert(phead);
	free(phead->top);
	phead->top = NULL;
	phead->size = 0;
	phead->capatipy = 0;

}
int StackSize(SNode* phead)
{
	assert(phead);

	return phead->size;
}
bool StackEmpty(SNode* phead)
{
	assert(phead);

	return phead->size == 0;
}

int StackTop(SNode* phead)
{
	return phead->top[phead->size - 1];
}

队列的概念及结构队列:

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

void QPush(Que* pq, QDataType x)
{
	assert(pq);

	QueNode* newnode = (QueNode*)malloc(sizeof(QueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;

	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
		newnode = NULL;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
		newnode = NULL;
	}
	pq->size++;
}
void QPop(Que* pq)
{
	assert(pq);
	assert(!QEmpty(pq));

	QueNode* pop = pq->phead;
	pq->phead = pop->next;
	free(pop);
	pop = NULL;
	pq->size--;
}
int QSize(Que* pq)
{
	assert(pq);

	return pq->size;
}
bool QEmpty(Que* pq)
{
	assert(pq);

	return pq->phead == NULL;
}
void QDestory(Que* pq)
{
	while (pq->phead)
	{
		QPop(pq);
	}
	pq->phead = pq->ptail = NULL;
}

QueNode* QueFront(Que* pq)
{
	assert(pq);
	assert(!QEmpty(pq));

	return pq->phead->val;
}

QueNode* QueBack(Que* pq)
{
	assert(pq);
	assert(!QEmpty(pq));

	return pq->ptail->val;
}

既然栈的特点是后进先出,而队列的特点是先进先出,那是否可以将俩者相互转换,用栈去实现队列,用队列去实现栈?

用栈去实现队列:

typedef struct Stack
{
    int* top;
    int capatipy;
    int size;
}ST;

typedef struct
{
    ST* ps1;
    ST* ps2;
} MyQueue;

MyQueue* myQueueCreate()
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if (obj == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    obj->ps1 = (ST*)malloc(sizeof(ST));
    if (obj->ps1 == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    obj->ps2 = (ST*)malloc(sizeof(ST));
    if (obj->ps2 == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    obj->ps1->top = (int*)malloc(sizeof(int)*4);
    if (obj->ps1->top == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    obj->ps2->top = (int*)malloc(sizeof(int)*4);
    if (obj->ps2->top == NULL)
    {
        perror("malloc fail");
        return NULL;
    }

    obj->ps1->size = obj->ps2->size = 0;
    obj->ps1->capatipy = obj->ps2->capatipy = 4;
    return obj;
}
bool myQueueEmpty(MyQueue* obj)
{
    return obj->ps1->size == 0 && obj->ps2->size == 0;
}
void STPush(ST* ps, int x)
{
    assert(ps);

    if (ps->size == ps->capatipy)
    {
        int* tmp = (int*)realloc(ps->top, sizeof(int) * 2 * (ps->capatipy));
        if (tmp == NULL)
        {
            perror("realloc fail");
            return;
        }

        ps->top = tmp;
        tmp = NULL;
        ps->capatipy *= 2;
    }
    ps->top[ps->size] = x;
    ps->size++;
}

void STPop(ST* ps)
{
    assert(ps);

    ps->size--;
}

void myQueuePush(MyQueue* obj, int x)
{
    STPush(obj->ps1, x);
}

int myQueuePop(MyQueue* obj)
{
    while (obj->ps1->size != 1)
    {
        STPush(obj->ps2, obj->ps1->top[obj->ps1->size - 1]);
        STPop(obj->ps1);
    }
    int data = obj->ps1->top[obj->ps1->size - 1];
    STPop(obj->ps1);
    while(obj->ps2->size)
    {
        STPush(obj->ps1, obj->ps2->top[obj->ps2->size - 1]);
        STPop(obj->ps2);
    }
    return data;
}

int myQueuePeek(MyQueue* obj)
{
    if (myQueueEmpty(obj))
    {
        return -1;
    }
    return obj->ps1->size == 0 ? obj->ps2->top[0] : obj->ps1->top[0];
}

void myQueueFree(MyQueue* obj)
{
    assert(obj);

    free(obj->ps1->top);
    free(obj->ps2->top);
    free(obj->ps1);
    free(obj->ps2);
    free(obj);
}

用栈实现队列的思想是:用俩个栈,一个栈实现进队列的功能,一个是实现出队列的功能。

用栈去实现队列应该注意的是:

当pop一次时,每出一次队列,那么可以发现把p1的数据push到p2会发生数据逆向存储,因此需要出完队列后重新入队列。

bool myQueueEmpty(MyQueue* obj)
{
    return obj->ps1->size == 0 && obj->ps2->size == 0;
}

其次:判空最好用size判,不要用head判,因此,head在你pop和push一次过后,如过p2->head没有主动置空,会发生非法访问。

用队列去实现栈:

typedef struct QueueNode{
    struct QueueNode* next;
    int val;
}QNode;
typedef struct Queue{
    QNode* head;
    QNode* tail;
    int size;
}Que;
typedef struct {
    Que* p1;
    Que* p2;
} MyStack;
MyStack* myStackCreate() {
    MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
    obj->p1=(Que*)malloc(sizeof(Que));
    obj->p2=(Que*)malloc(sizeof(Que));
    obj->p1->head=obj->p1->tail=obj->p2->head=obj->p2->tail=NULL;
    obj->p1->size=obj->p2->size=0;
    return obj;
}
bool myStackEmpty(MyStack* obj) {
    return obj->p1->head==NULL&&obj->p2->head==NULL;
}
void QueuePush(Que* pq,int x){
    assert(pq);
    QNode* newnode=(QNode*)malloc(sizeof(QNode));
    if(newnode==NULL){
        perror("malloc fail");
        return;
    }
    newnode->val=x;
    newnode->next=NULL;
    if(pq->head==NULL){
        pq->head=pq->tail=newnode;
    }
    else{
        pq->tail->next=newnode;
        pq->tail=newnode;
    }
    pq->size++;
}
void QueuePop(Que* pq){
    assert(pq);
    QNode* pop=pq->head;
    pq->head=pop->next;
    free(pop);
    pop=NULL;
    pq->size--;
    if(pq->size==0){
        pq->head=pq->tail=NULL;
    }
}
void myStackPush(MyStack* obj, int x) {
    if (obj->p1->size == 0) {
        QueuePush(obj->p2, x);
    } else {
        QueuePush(obj->p1, x);
    }
}

int myStackPop(MyStack* obj) {
    assert(!myStackEmpty(obj));
     if(obj->p2->size==0&&obj->p1->size!=0){
         while(obj->p1->head!=obj->p1->tail){
             QueuePush(obj->p2,obj->p1->head->val);
             QueuePop(obj->p1);
         }
         int pdata=obj->p1->head->val;
          QueuePop(obj->p1);
          return pdata;
     }
     if(obj->p1->size==0&&obj->p2->size!=0){
         while(obj->p2->head!=obj->p2->tail){
             QueuePush(obj->p1,obj->p2->head->val);
             QueuePop(obj->p2);
         }
         int pdata=obj->p2->head->val;
          QueuePop(obj->p2);
          return pdata;
     }
     return EOF;
}
int myStackTop(MyStack* obj) {
    assert(!myStackEmpty(obj));
    if (obj->p1->size == 0) {
        return obj->p2->tail->val;
    } else {
        return obj->p1->tail->val;
    }
}
void myStackFree(MyStack* obj){
    if (myStackEmpty(obj)) {
        return;
    }
   if(obj->p1->head==NULL&&obj->p2->head!=NULL){
       while(obj->p2->head){
           QNode* pop=obj->p2->head->next;
           free(obj->p2->head);
           obj->p2->head=pop;
       }
   }
   if(obj->p2->head==NULL&&obj->p1->head!=NULL){
       while(obj->p1->head){
           QNode* pop=obj->p1->head->next;
           free(obj->p1->head);
           obj->p1->head=pop;
       }
   }
   free(obj->p1);
   free(obj->p2);
   free(obj);
}

用队列去实现栈需要注意:

int myStackPop(MyStack* obj) {
    assert(!myStackEmpty(obj));
     if(obj->p2->size==0&&obj->p1->size!=0){
         while(obj->p1->head!=obj->p1->tail){
             QueuePush(obj->p2,obj->p1->head->val);
             QueuePop(obj->p1);
         }
         int pdata=obj->p1->head->val;
          QueuePop(obj->p1);
          return pdata;
     }
     if(obj->p1->size==0&&obj->p2->size!=0){
         while(obj->p2->head!=obj->p2->tail){
             QueuePush(obj->p1,obj->p2->head->val);
             QueuePop(obj->p2);
         }
         int pdata=obj->p2->head->val;
          QueuePop(obj->p2);
          return pdata;
     }
     return EOF;
}

在出栈的过程中使用俩个队列,存在元素的一个队列把非栈顶元素移到另一个空队列,同时把栈顶元素出栈,这样子的话,可以看出他不像以栈实现队列一样,会把数据存储顺序颠倒,但是,同样也有一个麻烦就是,栈顶元素出栈的过程中,含有当前栈顶元素的队列在栈顶元素出栈后,他的头指针和尾指针依旧指向那段存储空间,如果使用

obj->p2->head==NULL&&obj->p1->head!=NULL

这种以head判断的话,你没有不断置空,就会发生非法访问,因此,使用size判断会更好点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昨日青空。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值