在链栈的顺序存储实现中,关于链栈的初始化有不止一种方法例如:
typedef struct StackNode{
int data;
StackNode* next;
}* LinkStack;
void Init(LinkStack* s){
*s=NULL;
}
或者:
typedef struct StackNode{
int data;
StackNode* next;
}* LinkStack;
LinkStack Init(LinkStack s){
s=(LinkStack)malloc(sizeof(StackNode));
s=NULL;
return s;
}
以前我一直搞不清楚在C或C++中指针作为函数形参时到底是改变指针的指向还是指针指向的内容,今天在实现栈的链式存储时突然明白,在C语言中指针作为函数形参时无论在函数体内如何操作都不会改变实参指向的地址而只会改变指向地址中的内容;此时形参是实参的一个副本,相当于两个指针指向同一个地方,两个指针的指向互不干扰,但是如果其中一个指针(形参)改变了这个地方的内容,那么另一个指针虽然指向的位置没有发生改变但指向的内容却发生了改变。
同样的在链栈的其他基本操作比如:入栈,出栈操作中也是如此。
void Push(LinkStack s,int e){
LinkStack r=(LinkStack)malloc(sizeof(StackNode));
r->data=e;
if(!s){
r->next=NULL;
}else{
r->next=s;
}
s=r;
}
int main(){
LinkStack s;
s=Init(s);
for(int i=0;i<5;i++){
Push(s,i);
}
Print(s);//遍历栈
return 0;
}
如此执行,在遍历栈时会结果会直接输出:
因为在 void Push(LinkStack s,int e);中只是改变了形参s的指向而没有改变实参的指向自然无法实现初始化,解决方法有两种:
一、将函数的参数写作指向LinkStack的二级指针,可以直接改变外部指针指向
void Push(LinkStack *s,int e){
LinkStack r=(LinkStack)malloc(sizeof(StackNode));
r->data=e;
if(!(*s)){
r->next=NULL;
}else{
r->next=*s;
}
*s=r;
}
二、函数的参数仍为LinkStack型的指针,改变函数的返回值类型,将改变指向后的指针返回给外部指针
LinkStack Push(LinkStack s,int e){
LinkStack r=(LinkStack)malloc(sizeof(StackNode));
r->data=e;
if(!s){
r->next=NULL;
}else{
r->next= s;
}
s=r;
return s;
}
因为链栈的操作是通过不断改变指针指向来完成的,所以无法通过使用形参指针改变指向内容来改变外部指针指向的内容 。