参考文献:数据结构(c语言版)---严蔚敏p44----->p47
代码如下:
#include<stdlib.h>//malloc realloc
#include<iostream>//cin cout
using namespace std;
typedef int ElemType;/*元素类型*/
#define STACK_INIT_SIZE 100 /*栈存储空间初始化容量*/
#define STACKINCREMENT 10 /*栈存储空间每次的增量*/
/*管理栈的结构体*/
typedef struct
{
ElemType *base; /*栈底指针*/
ElemType *top; /*栈顶指针*/
int StackSize; /*栈的容量*/
}SqStack;
/*初始化栈*/
bool InitStack(SqStack *s)
{
s->base = (ElemType *)malloc(sizeof(ElemType)*STACK_INIT_SIZE);
if(!(s->base))/*判断申请空间是否成功,这一步不可省略*/
{
cout<<"申请空间失败"<<endl;
return false;
}
s->top = s->base;/*栈空时,栈顶和栈底重合*/
s->StackSize = STACK_INIT_SIZE;
return true;
}
/*入栈*/
bool Push(SqStack *s,ElemType e)
{
if(s->top - s->base >= s->StackSize)/*判断栈是否已满,如已满,动态增加容量*/
{
s->base = (ElemType *)realloc(s->base,sizeof(ElemType)*(s->StackSize+STACKINCREMENT));
if(!(s->base))
{
cout<<"申请空间失败"<<endl;
return false;
}
s->top = s->base + s->StackSize;/*问题一:为何要修改栈顶指针?????*/
s->StackSize += STACKINCREMENT;
}
*(s->top++) = e;
return true;
}
/*出栈*/
bool Pop(SqStack *s,ElemType *e)
{
if(s->top == s->base)
{
cout<<"栈已空"<<endl;
return false;
}
*e = *(--s->top);/*栈顶指针始终指向栈中最后一个元素的下一个元素,所以要先减一*/
return true;
}
/*清空栈*/
void ClearStack(SqStack *s)
{
s->top = s->base;
}
/*销毁栈*/
void DestoryStack(SqStack *s)
{
free(s->base);/*释放在栈上申请的空间*/
s->base = s->top = NULL;/*将栈顶指针和栈底指针赋空,防止被无意解引用*/
}
/*判断栈是否为空*/
bool StackEmpty(SqStack *s)
{
return s->base == s->top;
}
/*栈的长度,即栈中元素的个数*/
int StackLength(SqStack *s)
{
return s->top - s->base;/*问题二:地址相减得到什么??????*/
}
/*获得栈顶元素*/
bool GetTop(SqStack *s,ElemType *e)
{
if(StackEmpty(s))
{
cout<<"栈空"<<endl;
return false;
}
*e = *(s->top - 1);/*问题三:使用*(--s->top)不是等价么?????*/
return true;
}
/*主函数*/
int main()
{
SqStack s;
InitStack(&s);
int n;
cout<<"请输入要转化数值:"<<endl;
cin>>n;
while(n)
{
Push(&s,n%2);
n /= 2;
}
int e;
while(!StackEmpty(&s))
{
Pop(&s,&e);
cout<<e<<" ";
}
cout<<endl;
DestoryStack(&s);
return 0;
}
问题一:为何要修改栈顶指针?
bool Push(SqStack *s,ElemType e)
{
if(s->top - s->base >= s->StackSize)/*判断栈是否已满,如已满,动态增加容量*/
{
s->base = (ElemType *)realloc(s->base,sizeof(ElemType)*(s->StackSize+STACKINCREMENT));
if(!(s->base))
{
cout<<"申请空间失败"<<endl;
return false;
}
s->top = s->base + s->StackSize;/*问题一:为何要修改栈顶指针?????*/
s->StackSize += STACKINCREMENT;
}
*(s->top++) = e;
return true;
}
这与realloc的实现有关,先看一下msdn的一段话:
1、如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address
这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。
2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。
老块被放回堆上。
即:realloc函数执行完之后,存储空间可能已经改变,s->top所指的空间或许已经被释放(第二种情况),所以要修改s->top的指向!!!
问题二:指针相减,结果是什么:
/*栈的长度,即栈中元素的个数*/
int StackLength(SqStack *s)
{
return s->top - s->base;/*问题二:地址相减得到什么??????*/
}
当两个指针指向同一个数组时:指针相减得到的是两地址之间元素的个数问题三:(s->top - 1)与(-- s->top)是否等价
/*获得栈顶元素*/
bool GetTop(SqStack *s,ElemType *e)
{
if(StackEmpty(s))
{
cout<<"栈空"<<endl;
return false;
}
*e = *(s->top - 1);/*问题三:使用*(--s->top)不是等价么?????*/
return true;
}
使用(s->top - 1)与使用-- s->top的区别在于:
1)s->top - 1 执行之后,s->top的值不发生改变
2)--s->top 执行之后,s->top的发生改变,减了个一
获得栈顶元素的同时,不应该改变栈顶指针的指向,所以不是等价的