栈是一种数据结构,只要满足数据后进先出的数据结构都算是栈
栈按照构造类型可以分为两种:栈的顺序存储和栈的链式存储
栈的顺序存储
栈的顺序存储是将栈以数组的形式构造。通过算法来实现栈的后进先出。当以数组形式表示构建栈类型的数据结构时,将数组尾端,即数组中高索引的部分当作栈顶最为合适,因为这样的结构在栈进行出栈和进栈的时候不需要频繁的移动数组的元素。
下面用图和代码来说明栈的存储结构。
第一种:直接将数据存储在栈中
1.栈中若存储的是单一类型的数据结构。在这里以int型数据为例,但是也可以存储float、double等。特别的,因为编译器在为结构体分配内存空间的时候为结构体分配的是连续的内存空间,所以可以存储结构体类型的数据元素。只不过在存储结构体类型的数据元素的时候需要先构建结构体类型,然后将使用结构体名替换这里的int即可。
2.在下面这行代码中,int size在这里起到栈顶指针的作用。虽然记录的是栈中数据元素的个数,但是在栈的顺序存储结构中,知道了栈中元素的个数就相当于知道了栈顶元素所在的位置,并且也可以通过数组下标来操作栈顶的元素。所以在这里使用int size来代替指针型数据,使操作大大简化,避免一些内存管理容易出现的问题,同时也可以起到栈顶指针的作用。
#define Max 1024 struct seq_stack1 { //存储数据的部分 int num[MAX]; //说明栈的存储元素个数的变量 int size; }
示意图
如果存储的是若干种数据类型,则需要先将这若干个数据类型组合成一个结构体。如代码所示
#define MAX 1024 //先构建一个Person类 struct Person { char name[30]; int age; } //构建含有几种数据类型的结构体 struct data { struct Person Mary; int num; } //构建栈的结构体 struct seq_stack2 { struct data data1; int size }
栈中存储的是其他存储空间的首字节的地址。栈中每个元素的数据类型都是void*类型。
#define MAX 1024 //因为栈中的每个元素都是void*类型的,所以形参必须也是void*类型的 //又因为void*类型的数据能够接收任何类型的指针,所以也必须可以写成其他类型的形参 //但是在接收实参的时候必须接收的是地址 struct seq_stack2 { void *data; int size; }
示意图
以栈中元素为void*类型的栈书写初始化代码
typedef void* seqstack; seqstack init_seqstack() { seq_stack1* stack = malloc(sizeof(struct seq_stack1)); if (NULL == stack) { return; } for (int i = 0; i < MAX; i++) { stack->data[i] = NULL; } stack->size = 0; return stack; }
2.栈的链式存储
我们前面介绍了链表结构。使用链表结构来构造的栈称为链栈。
在这里我们使用链表来表示栈。
问题一: