实验三 栈的基本操作

ZZU的学弟学妹们不要抄作业哦~(`Д´)

一、实验目的
1.掌握栈的存储结构的表示和实现方法。
2.掌握栈的入栈和出栈等基本操作算法实现。
3.了解栈在解决实际问题中的简单应用。

二、实验内容
1.建立顺序栈,并在顺序栈上实现入栈和出栈操作。
2.建立链栈,并在链栈上实现入栈和出栈操作。

三、实验要求
1.建立顺序栈,并在顺序栈上实现入栈和出栈操作。
(1)根据输入的栈中元素个数n和各元素值建立一个顺序栈,并输出栈中各元素值。
(2)将数据元素e入栈,并输出入栈后的顺序栈中各元素值。
(3)将顺序栈中的栈顶元素出栈,并输出出栈元素的值和出栈后顺序栈中各元素值。
2.建立链栈,并在链栈上实现入栈和出栈操作。
(1)根据输入的栈中元素个数和各元素值建立一个链栈,并输出链栈中各元素值, 观察输入的内容与输出的内容是否一致,特别注意栈顶元素的位置。
(2)将数据元素x入栈,并输出入栈后的链栈中各元素值。
(3)将链栈中的栈顶元素出栈,并输入出栈元素的值和出栈后链栈中各元素值。

四、详细程序清单

//1.顺序栈 
#include
#include

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10

typedef struct{
	int *base;
	int *top;
	int stacksize;
}SqStack;

int Create(SqStack &S,int n) //创建  
{ 
    S.base = (int*)malloc(STACK_INIT_SIZE*sizeof(int));  
    if (!S.base)
	{
		printf("存储分配失败\n");
		return 0;
	}
    S.top=S.base;
    S.stacksize=STACK_INIT_SIZE;  
    printf("输入栈的元素:\n");
	for(int i=1;i<=n;i++)  
    	{        
        	scanf("%d",&*S.top); 
			S.top++;
    	}  
}  

int Show(SqStack S)//显示 
{  
    if (S.top==S.base)
	{
		printf("栈为空\n"); 
		return 0;  
	}   
    int *p;  
    p = S.top;  
    while (p>S.base)  
    {  
        p--;  
        printf("%d ",*p);  
    }  
    printf("\n"); 
} 

int Push(SqStack &S, int e)//入栈  
{  
    if (S.top-S.base>=S.stacksize)  
    {  
        S.base=(int *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(int));  
        if (!S.base)  
        {  
            printf("存储分配失败\n");
			return 0;
        }  
        S.top=S.base+S.stacksize; 
        S.stacksize+=STACKINCREMENT;  
    }  
    *S.top++=e;
} 

int Pop(SqStack &S)//出栈  
{
	int e;
    if (S.top==S.base) 
	{
		printf("栈为空\n"); 
		return 0;  		
	} 	
    else  
    {  
        e=*--S.top; 
        printf("出栈元素为%d\n",e); 
    }  
}  

int main()  
{  
	SqStack S;  
    int select,i,e,n; 
    while(1)  
    {   
        printf("1.创建栈 \t2.入栈 \t3.出栈\t4.退出\n");   
        scanf("%d",&select);  
        switch(select)  
        {    
        case 1:
			printf("输入栈的长度:\n");  
    		scanf("%d",&n);   
            Create(S,n);
			Show(S);  
            break;  
        case 2: 
        	printf("输入入栈元素\n");
        	scanf("%d",&e);  
        	Push(S,e);
			Show(S);
            break;    
		case 3:	
			Pop(S);
			Show(S);
			break; 
		case 4:  
			return 0;  
        default: 
		    printf("输入错误\n");
            break; 
        }  
    }  
    return 0;  
}  



//2.链栈 
#include   
#include   
  
typedef struct SNode{
int data;
struct SNode *next;
}SNode,*LinkStack;

LinkStack top,base;

int Show()//显示 
{
	LinkStack p;	
	printf("当前链栈元素为:");
	p=top;
	if(p==base)
	{
		printf("栈为空\n");
		return 0;
	}
    while(p!=NULL)  
    {  
        printf("%d ",p->data);  
        p=p->next;  
    } 
    printf("\n");  
}  
  
void Create(int n)//创建 
{
	LinkStack p;
	base=top;
	printf("输入栈的元素:\n");
	int x;
   	for(int i=1;i<=n;i++) 
    { 
    	scanf("%d",&x);
        p=(LinkStack)malloc(sizeof(SNode));  
        p->data=x;
        p->next=top;
		top=p;	
    }
} 

int Push(int e)//入栈 
{
	LinkStack p;
    p=(LinkStack)malloc(sizeof(SNode)); 
	p->data=e;
	p->next=top;
	top=p;	
}

int Pop()//出栈 
{
	LinkStack p;
	int e;
	if(top==base)
	{
		printf("栈为空\n");
		return 0;
	}
	p=top;
	e=p->data;	
	top=top->next;
	free(p);	
}

int main()  
{  
	LinkStack S;  
    int select,i,e,n;
    while(1)  
    {   
        printf("1.创建栈 \t2.入栈 \t3.出栈\t4.退出\n");   
        scanf("%d",&select);  
        switch(select)  
        {    
        case 1:
			printf("输入栈的长度:\n");  
    		scanf("%d",&n);   
            Create(n);
			Show();  
            break;  
        case 2: 
        	printf("输入入栈元素\n");
        	scanf("%d",&e);  
        	Push(e);
			Show();
            break;    
		case 3:	
			Pop();
			Show();
			break; 
		case 4:  
			return 0;  
        default: 
		    printf("输入错误\n");
            break; 
        }  
    }  
    return 0;  
}      

五、程序运行结果
1.顺序栈:

实验三 栈的基本操作_第1张图片

2.链栈:

实验三 栈的基本操作_第2张图片

六、实验心得体会
1.链栈和链表类似,不再多说;
2.顺序栈的操作用到了realloc这个函数,书上说是用来“追加”内存空间的,S.bace=(int *) realloc (S.stacksize+STACKINCREMENT) * sizeof(int)); 但是我有个疑惑:真的是在原来的内存后面追加内存吗?还是在另外的地方开辟新的空间?于是我用#define STACK_INIT_SIZE 3 #define STACKINCREMENT 10做实验,在打印栈中元素printf("%d “,*p);后面又加了一句printf(”%p ",p);来打印地址,结果发现的确是在原来位置的后面追加了内存(见下图):
实验三 栈的基本操作_第3张图片

但是新的疑问产生了:如果原内存后面已经被占用了又怎么办呢?我把条件改成#define STACK_INIT_SIZE 3 #define STACKINCREMENT 1000000000
果然,地址发生了改变(见下图):
实验三 栈的基本操作_第4张图片

也就是说并不是直接在原地址后面追加内存,而是换个地方开辟了新的内存空间。但是新的问题又出现了,我按书上内容写的程序,并没有将原地址上的data复制到新地址上啊,为什么原来栈中的内容依然能打印出来呢?这个问题我在网上找到了答案:
先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

原来计算机在我们看不到的地方做了这么多事。

你可能感兴趣的:(数据结构实验_C语言)