IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [数据结构] 五.详解栈以及两种存储结构的C语言实现 -> 正文阅读

[数据结构与算法][数据结构] 五.详解栈以及两种存储结构的C语言实现

目录

认识栈

三种物理结构

1.顺序储存结构

2.链式储存结构

3.共享栈

出栈顺序的特点

C语言实现

顺序栈

链式栈

共享栈


认识栈

栈也是一种线性的逻辑结构, 和顺序表与普通链表不同的是他的操作(运算)不同

复习一下数据结构的三要素: 逻辑结构, 物理(储存结构), 操作(运算)

栈有两端: 栈顶和栈底, 只能在栈顶进行增加(入栈)和删除(出栈)

所以栈可以看成是一种操作受限的线性表

栈的特点是先进后出

三种物理结构

1.顺序储存结构

用一个数组实现栈, 用一个额外的指针指向栈顶(一般把栈底固定)

2.链式储存结构

用链表实现栈, 链表的第一个节点表示栈顶, 最后一个节点表示栈底, 只在链表的头部进行删除和增加

3.共享栈

用一个长为n数组a实现两个栈, 这两个栈的栈顶分别在a[-1]和a[n](指向栈底说明是空栈), 栈顶向中间延伸, 只有当两个栈顶相距为1时栈才满, 更好地利用了空间

出栈顺序的特点

栈方面的考察点经常是给出入栈顺序, 判断某个出栈顺序是否存在

一般这样考虑:

例如入栈为1,2,3,4....n

  • 如果第1个出栈元素是n, 那么不用想了, 它是先全部入栈, 再全部出栈, 出栈顺序是n,n-1,n-2....1
  • 如果第2个出栈元素是n, 那么第1个出栈元素可以是任意一个, 但是第3个出栈元素只能是n-1或者n-2
  • 如果第3个出栈元素是n, 那么第1个和第2个出栈元素可以是任意一个, 但是第4个出栈元素只能是n-1,n-2,n-3
  • 以此类推...

C语言实现

顺序栈

/**
 * @file sequence_stack.c
 * @author xiaoxiao (you@domain.com)
 * @brief 顺序栈
 * @version 0.1
 * @date 2022-03-05
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxSize 10

typedef struct Stack {
    int* pData; // 数据
    int top; // 栈顶位置(-1表示空栈, 0表示当前栈有一个元素)
}Stack;

typedef Stack* PStack;

/**
 * @brief 初始化一个栈
 * 
 * @return PStack 栈指针
 */
PStack initailStack(){
    PStack pStack = (PStack) malloc (sizeof(PStack));
    if(pStack == NULL){
        printf("no more momery");
        exit(1);
    }
    pStack -> pData = (int*) malloc (MaxSize * sizeof(int));
    if(pStack -> pData == NULL){
        printf("no more momery");
        exit(1);
    }
    pStack -> top = -1; // 空栈
    return pStack;
}

/**
 * @brief 元素入栈
 * 
 * @param pStack 栈指针
 * @param data 入栈元素
 * @return true 入栈成功
 * @return false 入栈失败
 */
bool push(PStack pStack, int data){
    if(pStack -> top == MaxSize - 1){
        printf("栈已满, 无法进栈\n");
        return false;
    }
    pStack -> pData[pStack -> top ++ + 1] = data;
    return true;
}

/**
 * @brief 元素出栈
 * 
 * @param pStack 栈指针
 * @return int 出栈元素
 */
int pop(PStack pStack){
    if(pStack -> top == -1){
        printf("空栈不能出栈");
        return false;
    }
    return pStack -> pData[-- pStack -> top + 1];
}

/**
 * @brief 打印栈中元素
 * 
 * @param pStack 栈指针 
 * @return true 非空栈,可以打印
 * @return false 不是空栈
 */
bool printStack(PStack pStack){
    if(pStack -> top == -1){
        printf("空栈不能打印\n");
        return false;
    }
    printf("自栈底打印元素: ");
    for(int i = 0; i <= pStack -> top; i ++){
        printf("%d ", pStack -> pData[i]);
    }
    printf("\n");
    return true;
}

/**
 * @brief 销毁栈, 并释放栈空间
 * 
 * @param pStack 
 */
void destoryStack(PStack pStack){
    free(pStack -> pData);
    free(pStack);
}

int main(){
    printf("--------------------\n");
    PStack pStack = initailStack();
    push(pStack, 1);
    push(pStack, 10);
    push(pStack, 4);
    printStack(pStack);
    destoryStack(pStack);
    printf("--------------------");
    return 0;
}

链式栈

链式栈这里引用了我以前的写的链表的linked_list.h头文件

/**
 * @file linked_stack.c
 * @author xiaoxiao (you@domain.com)
 * @brief 链式栈
 * @version 0.1
 * @date 2022-03-05
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include <stdio.h>
#include "linked_list.h"

/**
 * @brief 初始化一个链式栈
 * 
 * @return PNode 头结点
 */
PNode initailStack(){
    return initalList();
}

/**
 * @brief 元素入栈
 * 
 * @param pStack 栈指针
 * @param data 入栈元素
 * @return true 入栈成功
 * @return false 入栈失败
 */
bool push(PNode pHead, int data){
    return insertByIndex(pHead, 1, data);
}

/**
 * @brief 元素出栈
 * 
 * @param pStack 栈指针
 * @return int 出栈元素
 */
int pop(PNode pHead){
    int x;
    if(pHead -> next != NULL){
        x = pHead -> next -> data;
        deleteByIndex(pHead, 1);
        return x;
    }
    printf("空栈无法出栈\n");
    return -1;
}

/**
 * @brief 打印栈中元素
 * 
 * @param pStack 栈指针 
 * @return true 非空栈,可以打印
 * @return false 不是空栈
 */
bool printStack(PNode pHead){
    if(pHead -> next == NULL){
        printf("空栈不能打印\n");
        return false;
    }
    PNode pCurrent = pHead;
    printf("自栈底打印元素: ");
    int l = getLength(pHead);
    int* data = (int*) malloc (l * sizeof(int)); 
    int i = 0;
    while (pCurrent -> next != NULL) {
        data[i ++] = pCurrent -> next -> data;
        pCurrent = pCurrent -> next;
    }
    for(i = 1; i <= l; i++)
        printf("%d ", data[l - i]);
    printf("\n");
    return true;
}

/**
 * @brief 销毁栈, 并释放栈空间
 * 
 * @param pStack
 */
void destoryStack(PNode pHead){
    destroyList(pHead);
}

int main(){
    printf("-----------------\n");
    PNode pHead = initailStack();
    push(pHead, 1);
    push(pHead, 4);
    pop(pHead);
    printStack(pHead);
    destoryStack(pHead);
    printf("-----------------");
    return 0;
}

共享栈

/**
 * @file shared_stack.c
 * @author xiaoxiao (you@domain.com)
 * @brief 共享栈
 * @version 0.1
 * @date 2022-03-06
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define MaxSize 20  // 总栈长

typedef struct Stack {
    int* pData;    // 数据
    int leftTop;   // 左栈顶(-1表示空栈, 0表示当前栈有一个元素)
    int rightTop;  // 右栈顶
} Stack;

typedef Stack* PStack;

/**
 * @brief 初始化一个栈
 *
 * @return PStack 栈指针
 */
PStack initailStack() {
    PStack pStack = (PStack)malloc(sizeof(PStack));
    if (pStack == NULL) {
        printf("no more momery");
        exit(1);
    }
    pStack->pData = (int*)malloc(MaxSize * sizeof(int));
    if (pStack->pData == NULL) {
        printf("no more momery");
        exit(1);
    }
    pStack->leftTop = -1;        // 左栈顶
    pStack->rightTop = MaxSize;  // 右栈顶
    return pStack;
}

/**
 * @brief 元素入栈
 *
 * @param pStack 栈指针
 * @param data 入栈元素,非负数就是向左入栈,负数就是向后入栈
 * @return true 入栈成功
 * @return false 入栈失败
 */
bool push(PStack pStack, int data) {
    if (pStack->leftTop + 1 == pStack->rightTop) {
        printf("栈已满, 无法进栈\n");
        return false;
    }
    if (data >= 0)
        pStack->pData[pStack->leftTop++ + 1] = data;
    else
        pStack->pData[pStack->rightTop-- - 1] = abs(data);
    return true;
}

/**
 * @brief 元素出栈
 *
 * @param pStack 栈指针
 * @param side 哪一侧的元素,true:左侧,false:右侧
 * @return int 出栈元素
 */
int pop(PStack pStack, bool side) {
    if (side) {
        if (pStack->leftTop == -1) {
            printf("空栈不能出栈\n");
            return -1;
        }
        return pStack->pData[pStack->leftTop--];
    } 
    else {
        if (pStack->rightTop == MaxSize) {
            printf("空栈不能出栈\n");
            return -1;
        }
        return pStack->pData[pStack->rightTop++];
    }
}

/**
 * @brief 打印栈中元素
 *
 * @param pStack 栈指针
 * @return true 非空栈,可以打印
 * @return false 不是空栈
 */
void printStack(PStack pStack) {
    if (pStack->leftTop == -1)
        printf("左栈为空,不能打印\n");
    else {
        printf("自左栈底打印元素: ");
        for (int i = 0; i <= pStack->leftTop; i++) {
            printf("%d ", pStack->pData[i]);
        }
        printf("\n");
    }
    if (pStack->rightTop == MaxSize)
        printf("右栈为空,不能打印\n");
    else {
        printf("自右栈底打印元素: ");
        for (int i = MaxSize - 1; i >= pStack->leftTop; i--) {
            printf("%d ", pStack->pData[i]);
        }
        printf("\n");
    }
}

/**
 * @brief 销毁栈, 并释放栈空间
 *
 * @param pStack
 */
void destoryStack(PStack pStack) {
    free(pStack->pData);
    free(pStack);
}

int main() {
    printf("--------------------\n");
    PStack pStack = initailStack();
    push(pStack, 1);
    push(pStack, -10);
    push(pStack, 4);
    printStack(pStack);
    destoryStack(pStack);
    printf("--------------------");
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:50:47  更:2022-03-10 22:51:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:27:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码