栈和队列报错调试
1.用栈实现队列
232. 用栈实现队列 - 力扣(LeetCode)
此题解题思路如下:
先将数据放在pushst栈里面,popst栈为空再把pushst栈里面的数据放进popst栈里面去,不为空则不执行。不为空时候直接拿取栈顶数据。
代码如下:
typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;void STInit(ST* pst);
void STDestroy(ST* pst);void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);//拿取栈顶数据bool STEmpty(ST* pst);
int STSize(ST* pst);void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;//表示top指向栈顶元素的下一个位置pst->top = 0;
}void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->capacity = pst->top = 0;
}void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void STPop(ST* pst)
{assert(pst);assert(pst->top >0);pst->top--;
}STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}bool STEmpty(ST* pst)//判断真假
{assert(pst);return pst->top == 0;
}int STSize(ST* pst)
{assert(pst);return pst->top;
}typedef struct
{ST pushst;ST popst;
} MyQueue;MyQueue* myQueueCreate()
{MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->pushst);STInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x)
{STPush(&obj->pushst, x);
}int myQueuePop(MyQueue* obj)
{int tmp=myQueuePeek(&obj->popst);STPop(&obj->popst);return tmp;
}int myQueuePeek(MyQueue* obj)
{if(STEmpty(&obj->popst)){while(!STEmpty(&obj->pushst)){STPush(&obj->popst, STTop(&obj->pushst));STPop(&obj->pushst);}}return STTop(&obj->popst);
}bool myQueueEmpty(MyQueue* obj)
{return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}void myQueueFree(MyQueue* obj)
{STDestroy(&obj->popst);STDestroy(&obj->pushst);free(obj);obj =NULL;
}/*** 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);
*/
报错1如下:
错误原因分析:
编译出错是运行问题,执行出错是代码逻辑问题,没有报结果大概率是头部出错。以此为基础推导出错原因,思路如下:
将上面代码拷贝至VS调试按照力扣所提供的测试样例进行传参,这道题我是使用栈实现代码进行解题,所以直接使用之前的实现代码进行调试,如果不知道栈的实现方法请观看这篇文章:
我们观察力扣所提供的测试样例:
我们先看力扣对这几个函数的传参设置:
函数"MyQueue"无传参值设置只需要一个返回值接受它,所以无需传参。调用两次"push"函数传结构体指针然后分别给x传1,2。剩下的"peek",“pop”,"empty"只需要传结构体指针。
但一般调试无需调用这么多函数,我调用了两个函数进行调试,调用如下:
int main()
{MyQueue* obj = myQueueCreate();myQueuePush(&obj, 1);return 0;
}
运行时候realloc函数会报错,出现内存不足的问题:
首先排除栈实现代码问题,因为实现时候调试过,没有报错,我们将问题范围缩小在实现队列部分,而初始化问题我前面已经解决了,那么排除初始化问题。因为是开辟空间报错,我们监视栈的结构体值变化,如图所示发现运行STPush函数的时候,栈的结构体里面的指针会变成野指针:
我们查看所有调用STPush的函数:
按思路走读一下代码,发现myQueuePop函数调用myQueuePeek函数时候我们想传的是出栈函数的地址给myQueuePeek函数进行调用,myQueuePeek函数调用STPush的函数我们想传的是出栈函数的地址给STPush函数进行调用,我们将此代码的思路图画出来,发现obj访问pushst结构体后再访问里面的pushst结构体,所以是传参错误,因为myQueuePeek函数里面已经传pushst的地址给STPush函数了,所以myQueuePop函数调用myQueuePeek函数只需要传obj指针调用即可。
报错2如下:
实现代码如下:
typedef struct
{ST* pushst;ST* popst;
} MyQueue;MyQueue* myQueueCreate()
{MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->pushst);STInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x)
{STPush(&obj->pushst, x);
}int myQueuePop(MyQueue* obj)
{int tmp=myQueuePeek(obj);STPop(&obj->popst);return tmp;
}int myQueuePeek(MyQueue* obj)
{if(STEmpty(&obj->popst)){while(!STEmpty(&obj->pushst)){STPush(&obj->popst, STTop(&obj->pushst));STPop(&obj->pushst);}}return STTop(&obj->popst);
}bool myQueueEmpty(MyQueue* obj)
{return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}void myQueueFree(MyQueue* obj)
{STDestroy(&obj->popst);STDestroy(&obj->pushst);free(obj);obj =NULL;
}
我们观察这段代码:
malloc函数开辟出来的指针只为MyQueue结构体开辟空间。但是MyQueue结构体里存放了两个结构体指针,不初始化就为空指针,初始化了为空指针,在栈实现的代码中assert(pst)会报错。不初始化会出现野指针访问报错,如果要写两个指针,需要再为这两个指针开辟空间。
STDestroy(&obj->popst);
STDestroy(&obj->pushst);
free(obj);
obj =NULL;
}
我们观察这段代码:[外链图片转存中...(img-RbuGxtYJ-1712389444934)]malloc函数开辟出来的指针只为MyQueue结构体开辟空间。但是MyQueue结构体里存放了两个结构体指针,不初始化就为空指针,初始化了为空指针,在栈实现的代码中assert(pst)会报错。不初始化会出现野指针访问报错,如果要写两个指针,需要再为这两个指针开辟空间。