公司面试要用C语言实现一个栈,之前做过用一个全局变量的指针来实现的,但是面试官要求在局部定义可以使用。
当时想的是利用指针的指针,但是没有想清楚为什么,现在总结一下。
首先参考这篇博客
https://blog.csdn.net/weixin_36040034/article/details/53351100
栈的底层可以用数组,可以用链表实现。
在C语言中,数组定义时必须为固定大小,因此实现栈时有容量限制。所以用栈来实现更为方便。
首先说数据结构,使用链表的话,需要有数据域,以及指向栈顶下一个元素的指针(最下面为栈底)
例如
typedef struct stack
{
datatype data;
struct stack* next;
}Stack;
这里需要注意,next前面这里不能用Stack,因为是先定义结构体,再执行typedef,在类型定义之前,编译器还不知道Stack是什么。
然后再说局部的问题,由于s指向的栈顶元素,因此不可避免的在入栈出栈的时候需要改变堆栈指针s的指向。
当然,前面说了,定义一个全局变量是很容易实现的,但是在实际工程中,不能定义很多全局变量的情况下,是有缺陷的。
因此,需要改变指针的指向,就有两种方式,一种是通过返回值返回堆栈指针,一种是通过指针的指针;
解释一下,为什么改变指针的指向需要指针的指针???
对于int *s = &a;如果直接在参数传递s,可以更改的是*s的值,但是更改s是不会生效的
因此,对于pop(s),如果改变了s的指向,对于调用者而言,s的指向并没有变,因此需要用到指针的指针,
也就是需要传递pop(&s),然后在里面利用*s去更改s的指向
下面附上用指针的指针实现的几个函数:pop(),push(),top(),init()
typedef struct stack{ int val; struct stack* next; }Stack; void Stack_Init(Stack** s) { *s = NULL; } void push(Stack** s, int val) { Stack* tmp = (Stack*)malloc(sizeof(Stack) * 1); if (tmp == NULL) return; tmp->val = val; tmp->next = (*s); *s = tmp; tmp = NULL; } void pop(Stack** s) { Stack* tmp = NULL; if (*s == NULL) return -1; else { tmp = *s; *s = (*s)->next; free(tmp); tmp = NULL; } } int top(Stack* s) { if (s == NULL) return -1; else return s->val; }