数组结构构成的栈
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//定义栈的长度为StackLength
#define ArrayStackLength 5
typedef struct ArrayStack{
int top;//指向栈顶的位置,其实是数组的下标
int stackArray[ArrayStackLength];//一个长度为StackLength,类型为int的数组
}ARRAYSTACK, *PARRAYSTACK;
//对栈的操作
//1创建一个空栈
void creatArrayStack(PARRAYSTACK pArrayStack);
//2.判断栈是否为空
bool isEmpty(PARRAYSTACK pArrayStack);
//3.判断栈是否为满
bool isFull(PARRAYSTACK pArrayStack);
//4.入栈
bool pushArrayStack(PARRAYSTACK pArrayStack, int value);
//5.出栈
bool popArrayStack(PARRAYSTACK pArrayStack, int *pValue);
//6.展示栈的元素
void showArrayStack(PARRAYSTACK pArrayStack);
int main(void) {
ARRAYSTACK arrayStack;
creatArrayStack(&arrayStack);
PARRAYSTACK pArrayStack = &arrayStack;
pushArrayStack(pArrayStack, 1);
pushArrayStack(pArrayStack, 11);
pushArrayStack(pArrayStack, 14);
pushArrayStack(pArrayStack, 9);
showArrayStack(pArrayStack);
int value = 0;
if (popArrayStack(pArrayStack, &value)) {
printf("出栈成功,出栈值为%d\n", value);
}
showArrayStack(pArrayStack);
return 0;
}
//1 创建一个空栈
void creatArrayStack(PARRAYSTACK pArrayStack)
{
pArrayStack->top = -1;
}
bool isEmpty(PARRAYSTACK pArrayStack)
{
if (pArrayStack->top >= 0) {
return false;
}else{
return true;
}
}
bool isFull(PARRAYSTACK pArrayStack)
{
if (pArrayStack->top == ArrayStackLength-1) {
return true;
}else{
return false;
}
}
bool pushArrayStack(PARRAYSTACK pArrayStack, int value)
{
if (isFull(pArrayStack)) {
return false;
}else{
//注意:++(pArrayStack->top)而不能写成(pArrayStack->top)++
pArrayStack->stackArray[++(pArrayStack->top)] = value;
return true;
}
}
bool popArrayStack(PARRAYSTACK pArrayStack, int *pValue)
{
if (isEmpty(pArrayStack)) {
return false;
}else{
//方法一
//*pValue = pArrayStack->stackArray[pArrayStack->top];//首先取出出栈的值
//pArrayStack->top--;//将top值减1
//方法二
//写在一起。但是需要注意是(pArrayStack->top)--而不能写成--(pArrayStack->top)
*pValue = pArrayStack->stackArray[(pArrayStack->top)--];
return true;
}
}
void showArrayStack(PARRAYSTACK pArrayStack)
{
if (isEmpty(pArrayStack)) {
printf("此栈为空栈\n");
return;
}
int tempTop = pArrayStack->top;
printf("此栈的元素分别为:");
for (int i = tempTop; i>=0; i--) {
printf("%d ", pArrayStack->stackArray[i]);
}
printf("\n");
}
在学习过程中,发现几个问题:
- 创建空栈的时候,是否可以使用如下代码:
void creatArrayStack(PARRAYSTACK pArrayStack)
{
pArrayStack = (PARRAYSTACK)malloc(sizeof(ARRAYSTACK));
if (NULL == pArrayStack) {
printf("分配空间失败\n");
exit(-1);
}
pArrayStack->top = -1;
}
首先ARRAYSTACK arrayStack;
语句,是创建一个ARRAYSTACK类型的名字叫arrayStack的结构体。该结构体虽然没有进行初始化,但是已经分配了内存空间,假如其内存空间为0x123456。
creatArrayStack(&arrayStack);
该语句是将arrayStack的地址传入creatArrayStack函数。将实参arrayStack的地址赋值给形参ARRAYSTACK pArrayStack。即ARRAYSTACK pArrayStack = &arrayStack;
这样,pArrayStack其实内部存储的是arrayStack的地址0x123456。
然而,pArrayStack = (PARRAYSTACK)malloc(sizeof(ARRAYSTACK));
这条语句的右边会新建一块内存,生成一个ARRAYSTACK类型的结构体,假如该结构体的存储地址为0x888888。然后用pArrayStack指针指向了0x888888。之后对pArrayStack->top = -1;
其实是对内存地址为0x888888里面的结构体进行top值修改。在creatArrayStack函数执行完毕后,pArrayStack仍然指向0x888888。但,main函数里面的&arrayStack
仍然是0x123456,这样等于该结构体并没有进行初始化,其里面的top值为垃圾值并不是-1。因此,这种方法是错误的。
- 是否可以用这种方法创建一个空栈:
PARRAYSTACK creatArrayStack(void)
{
PARRAYSTACK pArrayStack = (PARRAYSTACK)malloc(sizeof(ARRAYSTACK));
if (NULL == pArrayStack) {
printf("分配空间失败\n");
exit(-1);
}
pArrayStack->top = -1;
return pArrayStack;
}
这种方法是可以的。
- 在定义栈的时候,其内部的数组定义
int stackArray[ArrayStackLength];
是否可以用int *pBase;
用于指向数组第一个元素?
这样是可以的,只是对数组的表示方式不一样,如果用int *pBase;
表示数组,则该栈的创建与操作需要相应的修改。
链表结构构成的栈
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node{
struct Node *pNext;
int data;
}NODE, *PNODE;
typedef struct Stack{
PNODE pTop;
PNODE pBottom;
}STACK, *PSTACK;
//函数声明
void initStack(PSTACK pStack);
void pushStack(PSTACK pStack, int value);
void showStack(PSTACK pStack);
bool isEmptyStack(PSTACK pStack);
bool popStack(PSTACK pStack, int *pValue);
void clearStack(PSTACK pStack);
int main(void) {
STACK stack;
initStack(&stack);
pushStack(&stack, 1);
pushStack(&stack, 2);
pushStack(&stack, 3);
pushStack(&stack, 4);
showStack(&stack);
int value = 0;
if (popStack(&stack, &value)) {
printf("出栈成功,出栈元素为:%d \n", value);
}else{
printf("出栈失败\n");
}
// clearStack(&stack);
showStack(&stack);
return 0;
}
//函数实现
//初始化栈
void initStack(PSTACK pStack)
{
pStack->pTop = (PNODE)malloc(sizeof(NODE));
if (pStack->pTop == NULL) {
printf("分配空间失败!\n");
exit(-1);
}
pStack->pBottom = pStack->pTop;
pStack->pTop->pNext = NULL;
}
//入栈
void pushStack(PSTACK pStack, int value)
{
PNODE pNode = (PNODE)malloc(sizeof(NODE));
if (pNode == NULL) {
printf("分配空间失败");
exit(-1);
}
pNode->data = value;
pNode->pNext = pStack->pTop;
pStack->pTop = pNode;
}
void showStack(PSTACK pStack)
{
PNODE p = pStack->pTop;
while (p->pNext != NULL) {//while (p != pStack->pBottom)
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
}
bool isEmptyStack(PSTACK pStack)
{
if (pStack->pTop == pStack->pBottom) {
return true;
}else{
return false;
}
}
bool popStack(PSTACK pStack, int *pValue)
{
if (isEmptyStack(pStack)) {
return false;
}else{
*pValue = pStack->pTop->data;
PNODE p = pStack->pTop;
pStack->pTop = pStack->pTop->pNext;
free(p);
return true;
}
}
void clearStack(PSTACK pStack)
{
if (isEmptyStack(pStack)) {
return;
}else{
PNODE p = pStack->pTop;
PNODE q = NULL;
while (p->pNext != NULL) {//while (p != pStack->pBottom)
q = p->pNext;
free(p);
p = q;
}
pStack->pTop = pStack->pBottom;
}
}
对于清空操作,isEmptyStack(pStack)
操作也可以不做,因为下面的while循环条件其实也是这个,可以直接执行else里面的代码,有同样的效果。
为什么加上呢?
这是因为,在效率上,如果此栈本身为空栈,有判断条件可以直接结束。如果不加上这个判断条件,会直接执行PNODE p = pStack->pTop; PNODE q = NULL;
两句代码。这两句代码,分配了两个指针变量p和q,占据2x4个字节(32位机器)或2x8个字节(64位机器)。而且还有复制操作也需要占用内存。
其实,效率并没有提高多少。不写也没事。
对于栈的链式结构是下图中的A还是B
根据栈的定义,我们知道,只可以对栈的一端进行插入或者删除操作,该端称为栈顶。
对于链表的头,可以轻松进行插入或者删除操作,因此,链表的头可以做为栈顶;
对于链表的尾,可以进行插入操作,但由于其为一个单向链表,在尾部并不知道前一个指针是谁,因此不能进行删除操作。因此,链表的尾部不能做为栈顶;
因此,栈的链式结构是图中的A
对于栈的定义,在浙江大学-数据结构视频课中,这位老师对栈的定义直接跟线性表一样,只需要一个指针域与数据域。然后创建了一个头结点,指向了这个链表。这样也是可以的。通过对比可知,对于栈的定义,我们可以按照郝斌老师的定义方式,也可以按照浙大老师的定义方式。只要让单链表的一头进行插入或者删除就是栈,因此,栈的定义没有统一标准,能实现功能即可。
用一个数组存储两个栈,如何最大限度的利用好数组空间
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ArrayLength 5
//定义一个静态栈,top1从数组左边开始计算;top2从数组右边开始计算
typedef struct ArrayTwoStack{
int arrayData[ArrayLength];
int top1;//数组左边
int top2;//数组右边
}ARRAYTWOSTACK, *PARRAYTWOSTACK;
//初始化一个静态栈
void initArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack);
bool isEmpty(PARRAYTWOSTACK pArrayTwoStack, int type);//是否为空
bool isFull(PARRAYTWOSTACK pArrayTwoStack);//是否为满
void showArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int type);
void pushArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int value, int type);
void popArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int type);
int main(void) {
ARRAYTWOSTACK arrayTwoStack;
initArrayTwoStack(&arrayTwoStack);
pushArrayTwoStack(&arrayTwoStack, 1, 1);
pushArrayTwoStack(&arrayTwoStack, 2, 1);
pushArrayTwoStack(&arrayTwoStack, 111, 2);
pushArrayTwoStack(&arrayTwoStack, 222, 2);
pushArrayTwoStack(&arrayTwoStack, 333, 2);
popArrayTwoStack(&arrayTwoStack, 2);
showArrayTwoStack(&arrayTwoStack, 1);
showArrayTwoStack(&arrayTwoStack, 2);
pushArrayTwoStack(&arrayTwoStack, 333, 2);
return 0;
}
void initArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack)
{
pArrayTwoStack->top1 = -1;
pArrayTwoStack->top2 = ArrayLength;
}
bool isEmpty(PARRAYTWOSTACK pArrayTwoStack, int type)
{
if (type == 1) {//左边的栈
if (pArrayTwoStack->top1 >= 0) {
return false;
}else{
return true;
}
}else{//右边的栈
if (pArrayTwoStack->top2 >= ArrayLength) {
return true;
}else{
return false;
}
}
}
bool isFull(PARRAYTWOSTACK pArrayTwoStack)
{
if (pArrayTwoStack->top2 - pArrayTwoStack->top1 == 1) {
return true;
}else{
return false;
}
}
void pushArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int value, int type)
{
if (isFull(pArrayTwoStack)) {
printf("入栈失败,该栈已经满了\n");
exit(-1);
}
if (type == 1) {
pArrayTwoStack->arrayData[++(pArrayTwoStack->top1)] = value;
}else{
pArrayTwoStack->arrayData[--(pArrayTwoStack->top2)] = value;
}
}
void popArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int type)
{
if (isEmpty(pArrayTwoStack, type)) {
printf("出栈失败,该栈为空\n");
exit(-1);
}
if (type == 1) {
pArrayTwoStack->arrayData[--(pArrayTwoStack->top1)];
}else{
pArrayTwoStack->arrayData[++(pArrayTwoStack->top2)];
}
}
void showArrayTwoStack(PARRAYTWOSTACK pArrayTwoStack, int type)
{
if (type == 1) {
int tempTop = pArrayTwoStack->top1;
printf("该左边栈的元素为:");
for (int i = 0; i<=tempTop; i++) {
printf("%d ", pArrayTwoStack->arrayData[i]);
}
printf("\n");
}else{
int tempTop = pArrayTwoStack->top2;
printf("该右边栈的元素为:");
for (int i = ArrayLength-1; i>=tempTop; i--) {
printf("%d ", pArrayTwoStack->arrayData[i]);
}
printf("\n");
}
}