我们都知道,一个C/C++编译的程序中的一些局部变量,函数的参数值等都是放在栈里面的。虽说数据结构中的栈和内存中的栈并不完全相同,但是还是有相似点的。所以今天学习的内容就是数据结构中,如何来创建栈,如何进行数据的压入和压出,如何释放栈等等。本文主要介绍两种实现方法:1. 栈的链表实现;2. 栈的数组实现。直接看代码吧。(本文中所有的程序在anycodes.tk在线编程网站上测试通过)
1. 栈的链表实现
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
//struct Node;
//struct Stack;
//typedef struct Node* ptrToNode;
//typedef struct Stack* pStack;
typedef struct node
{
int element;
struct node * next;
}Node, *ptrToNode;
typedef struct stack
{
ptrToNode top; //栈顶
ptrToNode bottom; //栈底
}Stack,*pStack;
//创建链表
void createStack(pStack ptrStack)
{
ptrStack -> top = (ptrToNode)malloc(sizeof(Node)); //分配空间
if (ptrStack == NULL)
{
printf("Out of space!\n"); //分配空间失败
exit(1);
}
ptrStack -> bottom = ptrStack -> top; //使栈底元素指向栈顶元素
ptrStack -> top -> next = NULL; //使栈顶元素下一个元素指向空
}
void push(pStack ptrStack, int ele)
{
ptrToNode temp = (ptrToNode)malloc(sizeof(Node)); //创建一个临时的节点
if (temp == NULL)
{
printf("Out of space!\n"); //分配内存空间失败
exit(1);
}
temp -> element = ele; //先确定新的指针,后修改旧的指针
temp -> next = ptrStack -> top; //新指针先指向栈顶
ptrStack -> top = temp; //修改栈顶指向新push进来的节点
}
int isEmpty(pStack ptrStack)
{
return ptrStack->top->next == NULL;
}
int top(pStack ptrStack)
{
if(isEmpty(ptrStack))
{
printf("Sorry, the stack is blank!\n");
exit(1);
}
return ptrStack -> top -> element;
}
void pop(pStack ptrStack)
{
ptrToNode temp;
if(!isEmpty(ptrStack))
{
printf("Sorry, the stack is blank!\n");
exit(1);
}
temp = ptrStack -> top;
ptrStack -> top = ptrStack -> top -> next;
free(temp);
}
void printStack(pStack ptrStack)
{
ptrToNode temp = ptrStack -> top;
printf("The element in the stack from top to bottom is : \n");
while(temp != ptrStack -> bottom)
{
printf("%d ",temp -> element);
temp = temp -> next;
}
printf("\n");
}
int main()
{
int a[3] = {12,4354,657};
int i = 0;
int topElement = 0;
Stack s;
createStack(&s); //创建栈
for (; i < 3; i++)
{
push(&s, a[i]); //进栈
}
printStack(&s);
topElement = top(&s); //print the top element in the stack
printf("The top element is %d\n",topElement);
pop(&s);
printStack(&s);
return 0;
}
在anycodes(anycodes.tk) 在线编程网站上的测试结果:
2.栈的数组实现
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct Stack;
typedef struct Stack *pStack;
struct Stack
{
int Capacity;
int TopofStack;
int *Array;
};
#define MinStack -1
#define EmptyTOS -1
//创建链表
void createStack(pStack ptrStack, int EleNum)
{
if(EleNum < MinStack)
{
printf("Sorry, the length of the stack is to small!\n");
exit(1);
}
// ptrStack = malloc(sizeof(struct Stack)); //给栈结构体分配空间
if (ptrStack == NULL)
{
printf("Out of space!\n"); //分配空间失败
exit(1);
}
ptrStack -> Array = malloc(sizeof(int)*EleNum); //给数组分配空间
if (ptrStack -> Array == NULL)
{
printf("Out of space!\n"); //分配空间失败
exit(1);
}
ptrStack -> Capacity = EleNum;
ptrStack -> TopofStack = EmptyTOS;
}
int isFull(pStack ptrStack)
{
return ptrStack -> TopofStack == ptrStack -> Capacity -1;
}
void push(pStack ptrStack, int ele)
{
if(isFull(ptrStack))
{
printf("Sorry, the stack is full!\n");
exit(1);
}
ptrStack -> TopofStack = ptrStack -> TopofStack + 1;
ptrStack -> Array[ptrStack->TopofStack] = ele;
}
int isEmpty(pStack ptrStack)
{
return ptrStack -> TopofStack == EmptyTOS;
}
int top(pStack ptrStack)
{
if(isEmpty(ptrStack))
{
printf("Sorry, the stack is blank!\n");
exit(1);
}
return ptrStack -> Array[ptrStack -> TopofStack];
}
void pop(pStack ptrStack)
{
if(isEmpty(ptrStack))
{
printf("Sorry, the stack is blank!\n");
exit(1);
}
ptrStack -> TopofStack--;
}
void printStack(pStack ptrStack)
{
int i = ptrStack -> TopofStack;
printf("The element in the stack from top to bottom is : \n");
while(i >= 0)
{
printf("%d ",ptrStack -> Array[i--]);
}
printf("\n");
}
void freeStack(pStack ptrStack)
{
free(ptrStack -> Array);
free(ptrStack);
}
int main()
{
int a[3] = {12,4354,657};
int i = 0;
int topElement = 0;
pStack s;
s = malloc(sizeof(struct Stack));
createStack(s,3); //创建栈
for (; i < 3; i++)
{
push(s, a[i]); //进栈
}
printStack(s);
topElement = top(s); //print the top element in the stack
printf("The top element is %d\n",topElement);
pop(s);
printStack(s);
freeStack(s);
return 0;
}
在anycodes(anycodes.tk) 在线编程网站上的测试结果:
3. 两种实现方法的性能比较
链表的实现方法的所有的操作都花费常数时间,但是这种方法的缺点在于对malloc和free的调用的开销是安规的,特别是与指针操作的例程相比尤其如此。相比而言,数组的实现方法不仅以常数时间运行,而且是以非常快的常数时间运行。在某些极其上,若在带有自增和自减的寻址功能的寄存器上操作,则Push和Pop都可以写成一条机器指令。但是错误检测(如检测栈空下的Pop和栈满下的Push操作的数组越界问题)会影响栈的执行效率。在很多程序编写中,往往会省略错误检查,但是我们应该养成随时编写错误检测代码的好习惯。
欢迎大牛留言,进行批评与指正。