数据结构之栈的创建与操作(四)

数组结构构成的栈

#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");
}

在学习过程中,发现几个问题:

  1. 创建空栈的时候,是否可以使用如下代码:
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。因此,这种方法是错误的

在这里插入图片描述

  1. 是否可以用这种方法创建一个空栈:
PARRAYSTACK creatArrayStack(void)
{
    PARRAYSTACK pArrayStack = (PARRAYSTACK)malloc(sizeof(ARRAYSTACK));
    if (NULL == pArrayStack) {
        printf("分配空间失败\n");
        exit(-1);
    }
    pArrayStack->top = -1;
    return pArrayStack;
}

这种方法是可以的。

  1. 在定义栈的时候,其内部的数组定义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");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值