16 - 11 - 07 入栈时,内存中的 小变化

在这里摘出来了一个普通的入栈函数,但因为对指针的理解任重道远,所以对每一步代码,都用了打印地址的方法追踪其变化。
注:这整个函数的目的是通过 构建 - 插入的方式来构建 链栈 。
—-原函数—-:


LinkStack Push(LinkStack top,int e) //入栈函数
{
   LinkStack p; 
   p=(LinkStack)malloc(sizeof(SNODE));

   if (!p) 
      printf(" 栈溢出!!\n");

   p->data=e; 
   p->next=top; 
   top=p; 

   return top; 
} 

对 p->next=top;
top=p; 并不能深刻理解,故添足如下

LinkStack Push(LinkStack top,int e)
{  /*LinkStack型函数返回LinkStack型指针*/ 

  LinkStack p; 
  p=(LinkStack)malloc(sizeof(SNODE)); 
  if (!p) 
  printf("  栈溢出!!\n");


  p->data=e;
    printf("%p\n",p); 
    printf("%p\n",p->next);
    printf("%p\n",p->next->next); 
    printf("%p\n\n",p->next->next->next); //(无规律)
    printf("%p\n",top);             //top的地址当然为空。 
  p->next=top; //新结点插入到链表头部,成为新的栈顶元素
    printf("%p\n",p);
    printf("%p\n",p->next);    
  top=p;  
    printf("%p\n\n",top);   


    return top; 
}      // 这里加上了八个 printf() 来打印地址。

—-输出结果—–:

理解一:
这是第一趟运行(第一次循环)也就是输入第一个值时的程序输出,
我们发现,此时 p->next 的指向是没有规律的,因为我们现在
并没有给他施加定义,所以 p 用 next 乱指(= =) 。
top也因为没有进行准确定义,地址当然为空。

我们删掉四个打印p_>next….的函数

  p->data=e;
    printf("%p\n",top);             
  p->next=top;     
    printf("%p\n",p);
    printf("%p\n",p->next);    
  top=p;  
    printf("%p\n\n",top); 

当陆续输入下面的值()后,程序输出如下:
这里写图片描述

因为随着用户不断输入,p不断地被赋地址值,指向新开辟的内存区。

—从地址变化,也可以看出每次 p 被赋新的地址值的变化是:
6E80->6EA0->6EC0->6EE0;

—紧随 p 的 p->next 的变化是:
0000-> 6E80->6EA0->6EC0 ;

—这似乎能印证我们的解释:

p = (..)malloc(..);
p->next=top;
top=p;

比如在第三次循环中,
top 与 p->next中储存的,实际上是是上一次给 p 分配的地址,
由此构成一个循环来实现 元素的插入。

看图就更明白了:
这里写图片描述

全部代码

#include<stdio.h>
#include<stdlib.h>
typedef struct Snode 
{
 int data;/*数据域*/ 
 struct Snode *next;/*指针域*/ 
}SNODE,* LinkStack;/*其中SNODE为链栈中的结点类型名, LinkStack为指向结点的指针类型名*/ 
//////////////////
LinkStack Push(LinkStack top,int e) 
/*将数据元素e压入到链栈top中,使其成为新的栈项元素*/ 
{
 LinkStack p; 
 p=(LinkStack)malloc(sizeof(SNODE)); /*生成一个新的结点*/ 
 if (!p) /*如果分配空间失败,则函数返回"OVERFLOW"*/ 
  printf("Stack is Overflow\n");
 p->data=e; /*新结点的数据域赋值*/ 
 p->next=top; /*修改链使新结点插入到链表的头部,并成为新的栈顶元素*/ 
 top=p; 
 return top; 
} 
/////////////
LinkStack Pop(LinkStack top, int * e) 
/*将链栈top中的栈顶元素从栈中删除,并用e返回其值*/ 
{
 LinkStack q; 
 if (!top) /*如果栈空,则函数返回ERROR*/ 
  printf("Stack is ERROR\n"); 
 *e=top->data; /*将被删的栈顶元素的值保存在e中*/ 
 q=top; /*用q记下待删的栈顶元素*/ 
 top=q->next; 
 /*修改链使待删结点从链中"卸下" ,此时被删结点的后继成为新的栈顶元素结点*/ 
 free(q); /*释放被删结点的存储空间*/ 
 return top;
}
/////////
LinkStack Stack_display(LinkStack top)
{
 int e;
 while(top)
 {
  e=top->data;
  printf("%4d",e);
  top=top->next;
 }
 return top;
}
/////////////////////
void main()
{
 LinkStack top = 0; 
 int i=0,n,e; 
 printf("please input the length:");/*输入几个数*/ 
 scanf("%d",&n); 
 printf("please input the Value:\n");/*输入*/ 
 while(i<n)
 {
  scanf("%d",&e);
  top=Push(top,e);
  i++;
 }
 printf("the stack is:\n"); 
 Stack_display(top);
 printf("please input the insert node:"); 
 scanf("%d",&e); 
 top=Push(top,e);
 printf("the stack after push is:\n");
 Stack_display(top); 
 top=Pop(top,&e);
 printf("the pop value is:%d\n",e); 
 printf("the stack after pop is:\n");
 Stack_display(top); 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值