堆栈 订阅
在计算机领域,堆栈是一个不容忽视的概念,堆栈是一种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。 展开全文
在计算机领域,堆栈是一个不容忽视的概念,堆栈是一种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。
信息
外文名
Stack
定    义
一种数据项按序排列的数据结构
特    点
先进后出
中文名
堆栈
学    科
计算机
应    用
内存分配
堆栈简介
堆栈是一个特定的存储区或寄存器,它的一端是固定的,另一端是浮动的 [1]  。对这个存储区存入的数据,是一种特殊的数据结构。所有的数据存入或取出,只能在浮动的一端(称栈顶)进行,严格按照“先进后出”的原则存取,位于其中间的元素,必须在其栈上部(后进栈者)诸元素逐个移出后才能取出。在内存储器(随机存储器)中开辟一个区域作为堆栈,叫软件堆栈;用寄存器构成的堆栈,叫硬件堆栈。单片机应用中,堆栈是个特殊存储区,堆栈属于RAM空间的一部分,堆栈用于函数调用、中断切换时保存和恢复现场数据。堆栈中的物体具有一个特性:第一个放入堆栈中的物体总是被最后拿出来, 这个特性通常称为先进后出 (FILO—First-In/Last-Out)。 堆栈中定义了一些操作, 两个最重要的是PUSH和POP。 PUSH(入栈)操作:堆栈指针(SP)加1,然后在堆栈的顶部加入一 个元素。POP(出栈)操作相反,出栈则先将SP所指示的内部ram单元中内容送入直接地址寻址的单元中(目的位置),然后再将堆栈指针(SP)减1。这两种操作实现了数据项的插入和删除。
收起全文
精华内容
参与话题
问答
  • 堆栈

    千次阅读 多人点赞 2016-03-06 16:51:04
    九曲迷宫,也不过是修在...堆栈一般分为”专用堆栈存储器“和“软件堆栈” 1、专用堆栈存储器:就是专门设计的硬件存储器 2、软件堆栈:程序员在内存中划一块出来,当做堆栈使用(8088、8086) 堆栈的结构 8086、

    九曲迷宫,也不过是修在地面上的墙

    堆栈究竟是什么?
    堆栈是一个特定的存储区,访问该存储区一般需要按照专门的规则进行操作。
    堆栈是干嘛的?
    1、暂存数据
    2、在过程调用或处理中断时保存断点信息。
    堆栈的分类?
    堆栈一般分为”专用堆栈存储器“和“软件堆栈”
    1、专用堆栈存储器:就是专门设计的硬件存储器
    2、软件堆栈:程序员在内存中划一块出来,当做堆栈使用(8088、8086)
    堆栈的结构
    8086、8088中,堆栈是由堆栈段寄存器SS指示的一段存储区。
    这里写图片描述
    1、堆栈的一端是固定的,称为栈底。栈底是堆栈存储区的最大地址单元。
    2、堆栈另一端是浮动的,称为栈顶。在任何时刻,栈顶是最后存入信息的存储单元。栈顶是随着堆栈中存放信息的多少而改变。
    3、通常设置一个寄存器来指示栈顶位置。其内容就象一个指针一样,因此被称为堆栈指针SP(Stack Pointer)。
    4、在堆栈中存取数据的规则是:“先进后出FILO”

    数据在堆栈中以字为单位存放,低8位放在较低地址单元,高8位放在较高地址单元。

    SP被初始化时指向栈底+2单元,其值就是堆栈的长度。由于SP是16位寄存器,因此堆栈长度 64K字节。

    SP始终表示堆栈段基址与栈顶之间的距离(字节数)。
    当SP为最大(初始)值时,表示堆栈为空。
    当SP为0时,表示堆栈全满。

    当用户程序中要求的堆栈长度超过一个堆栈段的最大长度64KB时,可以设置多个堆栈段。

    什么叫“以字为单位”呢?
    1、任何两个相邻字节单元就构成一个字单元(一字节8位,一个字就是16位!)
    2、字单元的地址 为两个字节单元中较小地址字节单元的地址。
    3、字数据的存放规则是:低8位放在较低地址字节单元中,高8位放在较高地址字节单元中。
    展开全文
  • 堆栈溢出

    千次阅读 2019-03-26 22:10:13
    堆栈:是一个在计算机科学中经常使用的抽象数据类型,堆栈是一块保存数据的连续内存。 一个名为堆栈指针(SP)的寄存器指向堆栈的顶部,堆栈的底部在一个固定的地址。 堆栈中的物体具有一个特性: 最后一个放入堆栈中的...

    堆栈:是一个在计算机科学中经常使用的抽象数据类型,堆栈是一块保存数据的连续内存。 一个名为堆栈指针(SP)的寄存器指向堆栈的顶部,堆栈的底部在一个固定的地址。
    堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列。 堆栈中定义了一些操作。 两个最重要的是PUSH和POP。 PUSH操作在堆栈的顶部加入一 个元素。POP操作相反, 在堆栈顶部移去一个元素, 并将堆栈的大小减一。

    堆栈的顶部。 堆栈的底部在一个固定的地址。

    堆栈溢出的产生:是由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址

    一般在递归中产生:堆栈溢出很可能由无限递归(Infinite recursion)产生,但也可能仅仅是过多的堆栈层级。

    展开全文
  • 6-7 在一个数组中实现两个堆栈 (20 point(s)) 本题要求在一个数组中实现两个堆栈。 函数接口定义: Stack CreateStack( int MaxSize ); bool Push( Stack S, ElementType X, int Tag ); ElementType Pop...

    @https://pintia.cn/problem-sets/15/problems/730

    6-7 在一个数组中实现两个堆栈 (20 point(s))

    本题要求在一个数组中实现两个堆栈。

    函数接口定义:

    Stack CreateStack( int MaxSize );
    bool Push( Stack S, ElementType X, int Tag );
    ElementType Pop( Stack S, int Tag );
    

    其中Tag是堆栈编号,取12MaxSize堆栈数组的规模;Stack结构定义如下:

    typedef int Position;
    struct SNode {
        ElementType *Data;
        Position Top1, Top2;
        int MaxSize;
    };
    typedef struct SNode *Stack;
    

    注意:如果堆栈已满,Push函数必须输出“Stack Full”并且返回false;如果某堆栈是空的,则Pop函数必须输出“Stack Tag Empty”(其中Tag是该堆栈的编号),并且返回ERROR

    裁判测试程序样例:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define ERROR 1e8
    typedef int ElementType;
    typedef enum { push, pop, end } Operation;
    typedef enum { false, true } bool;
    typedef int Position;
    struct SNode {
        ElementType *Data;
        Position Top1, Top2;
        int MaxSize;
    };
    typedef struct SNode *Stack;
    
    Stack CreateStack( int MaxSize );
    bool Push( Stack S, ElementType X, int Tag );
    ElementType Pop( Stack S, int Tag );
    
    Operation GetOp();  /* details omitted */
    void PrintStack( Stack S, int Tag ); /* details omitted */
    
    int main()
    {
        int N, Tag, X;
        Stack S;
        int done = 0;
    
        scanf("%d", &N);
        S = CreateStack(N);
        while ( !done ) {
            switch( GetOp() ) {
            case push: 
                scanf("%d %d", &Tag, &X);
                if (!Push(S, X, Tag)) printf("Stack %d is Full!\n", Tag);
                break;
            case pop:
                scanf("%d", &Tag);
                X = Pop(S, Tag);
                if ( X==ERROR ) printf("Stack %d is Empty!\n", Tag);
                break;
            case end:
                PrintStack(S, 1);
                PrintStack(S, 2);
                done = 1;
                break;
            }
        }
        return 0;
    }
    
    /* 你的代码将被嵌在这里 */
    

    输入样例:

    5
    Push 1 1
    Pop 2
    Push 2 11
    Push 1 2
    Push 2 12
    Pop 1
    Push 2 13
    Push 2 14
    Push 1 3
    Pop 2
    End
    

    输出样例:

    Stack 2 Empty
    Stack 2 is Empty!
    Stack Full
    Stack 1 is Full!
    Pop from Stack 1: 1
    Pop from Stack 2: 13 12 11
    

    代码实现©

    Stack CreateStack(int MaxSize)
    {
        Stack p = (Stack)malloc(sizeof(struct SNode));
        p->Data = (int*)malloc(MaxSize * sizeof(int));
        p->Top1 =- 1;
        p->Top2 = MaxSize;
        p->MaxSize = MaxSize;
        return p;
    }
    bool Push(Stack S, ElementType X, int Tag)
    {
        if (S->Top2 - S->Top1 == 1)
        {
            puts("Stack Full");
            return 0;
        }
        if (Tag == 1)
            S->Data[++(S->Top1)] = X;
        else S->Data[--(S->Top2)] = X;
        return 1;
    }
    ElementType Pop(Stack S, int Tag)
    {
        if (Tag == 1)
        {
            if (S->Top1 == -1)
            {
                printf("Stack %d Empty\n", Tag);
                return ERROR;
            }
            return S->Data[(S->Top1)--];
        }
        else
        {
            if (S->Top2 == S->MaxSize)
            {
                printf("Stack %d Empty\n", Tag);
                return ERROR;
            }
            return S->Data[(S->Top2)++];
        }
    }
    
    展开全文
  • 的值,在切换任务或者中断的时候,是如何被保存到对应的任务堆栈中的,又是如何将 即将运行的任务堆栈的内容拷贝到CPU运行的寄存器中? 我看了ucos上相关的两段汇编,完全看不懂,不知道前辈能否指教一下,不胜感激...
  • JavaScript执行堆栈

    万次阅读 2019-05-10 08:01:59
    我们首先看JavaScript的函数底层工作原理 一个函数运行的信息被存储在它的执行上下文里。...与它关联的执行上下文被一个叫做执行上下文堆栈的特殊数据结构保存; 执行嵌套调用; 嵌套调用结束后...

    我们首先看JavaScript的函数底层工作原理
    一个函数运行的信息被存储在它的执行上下文里。
    执行上下文是一个内部数据结构,它包含一个函数执行时的细节:当前工作流在哪里,当前的变量,this的值(这里我们不使用它),以及其他一些内部细节。
    每个函数有嵌套调用时,下面的事情会发生:

    • 当前函数被暂停;
    • 与它关联的执行上下文被一个叫做执行上下文堆栈的特殊数据结构保存;
    • 执行嵌套调用;
    • 嵌套调用结束后,之前的执行上下文从堆栈中恢复,外部函数从停止的地方继续执行。
      我们看看调用pow(2, 3)都发生了什么。
      pow(2, 3)
      在调用pow(2, 3)的开始,执行上下文会存储变量:x = 2, n = 3,执行流程在函数的第1行。
      我们将其描绘如下:
      在这里插入图片描述
      这是函数开始执行的时候,条件 n == 1结果为否,所以流程进入if的第二分支。
    function pow(x, n) {
    	if (n == 1) {
    		return x;
    	} else {
    		return x * pow(x, n - 1);
    	}
    }
    alert(pow(2, 3));
    

    变量相同,但是函数变化了,所以现在上下文是:
    在这里插入图片描述
    为了计算x * pow(x, n - 1),我们需要用新的参数pow(2, 2)自调用pow。
    pow(2, 2)
    为了执行嵌套调用,JavaScript会记住执行上下文堆栈中的当前执行上下文。
    这里我们调用相同的函数pow,但是没关系。所有函数的处理都是一样的:
    1.当前上下文被「记录」在堆栈的顶部;
    2.为子调用创建新上下文;
    3.当子调用结束后 —— 前一上下文从堆栈弹出,继续执行。
    下面是进入子调用pow(2, 2)的上下文堆栈:
    在这里插入图片描述
    新的当前执行上下文位于顶部(加粗),前面的在下方。
    在我们完成子调用后—— 很容恢复前面的上下文,因为它保留这变量和代码停止时的准确位置。图中我们使用了单词「行」,但实际比这更精确。
    pow(2, 1)
    重复该过程:在第5行生成新的子调用,现在使用参数x = 2, n = 1。
    新的执行上下文被创建,前一个被压入堆栈顶部:
    在这里插入图片描述
    此时,有俩个旧的上下文和一个当前正在运行的给pow(2, 1)的上下文。
    出口
    在 pow(2, 1) 时,不像之前,条件 n == 1 成了是,所以 if 的第一分支生效:

    function pow(x, n) {
    	if (n == 1) {
    		return x;
    	} else {
    		return x * pow(x, n - 1);
    	}
    }
    

    此时不再有嵌套调用,所以函数结束,返回2。
    函数结束后,它的执行上下文不再有用,会在内存中移除。前一上下文从栈顶恢复:
    在这里插入图片描述
    恢复执行pow(2, 2),它有子调用pow(2, 1)的结果,所以它也可以结束x * pow(x, n - 1) 的执行,返回 4。
    然后前一上下文被恢复:
    在这里插入图片描述
    当它结束后,我们得到结果pow(2, 3) = 8。
    递归深度是:3。
    从上面的图解可以看到,递归深度等于堆栈中上下文的最大个数。
    注意内存要求。上下文消耗内存,在我们的例子中,求n次放需要存储n个上下文,以便减一后的n使用。
    而循环算法更省内存:

    function pow(x, n) {
    	let result = 1;
    	for (let i = 0; i < n; i++) {
    		result *= x;
    	}
    	return result;
    }
    

    迭代pow仅使用一个上下文,在处理中修改i和result。它的内存要求比较小,且固定不依赖n。
    任何递归都可以用循环来重写。循环变体一般更加有效。
    但有时重写很难,尤其是函数根据条件使用不同的子调用,然后合并它们的结果,或者分支比较复杂。而且有些优化可能没有必要,完全不值得。
    递归能提供更简洁的代码,容易理解和维护。优化并不是处处需要,大多数时候我们需要一个好代码,这就是它被使用的原因。

    展开全文
  • vs2015调试程序调用堆栈窗口看不到堆栈信息,显示为: [下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号] ![图片说明](https://img-ask.csdn.net/upload/201610/27/1477552322_979966.png) ![图片...
  • 最近在看java集合框架,有列表啊,散列,堆栈等概念。感觉这是以数组,java代码为基础的处理数据集合的容器。但是之前经常 看到说内存就是种堆和栈,而内存这块是jvm帮我们处理的,也就是说不是java代码关心的内容...
  • 5-2 堆栈操作合法性

    2016-04-16 07:02:10
    如果根据一个仅由S和X构成的序列,对一个空堆栈进行操作,相应操作均可行(如没有出现删除时栈空)且最后状态也是栈空,则称该序列是合法的堆栈操作序列。请编写程序,输入S和X序列,判断该序列是否合法。 输入格式...
  • Windbg -- 查看调用堆栈

    万次阅读 2018-02-12 17:19:45
    显示堆栈信息 k*命令 [~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] [FrameCount] [~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr [FrameCount] [~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr StackPtr...
  • 想用堆栈解决二进制到十进制 但是始终有错误 代码如下 int inversion(double i) { double temp; Stack S; setNull(&S); double sum=0; for(i=0;i;i++) { pop(&S); sum = sum + temp*pow(2,i); } ...
  • 而在C++中,对象是在堆栈中创建的。这样可达到更快的速度,”这句话不能理解。c++的堆栈和java的堆有啥区别啊。 PS:原文“最重要的一种情况是C和C++对内存的管理方式,它是某些人觉得Java速度肯定慢的重要依据:在...
  • 堆栈堆栈大小

    2016-03-17 21:01:00
    正在执行的程序为执行该程序的初始(或主)线程维护一个主堆栈,并为每个从属线程维护不同的堆栈堆栈是临时内存地址空间,用于保留子程序或函数引用调用期间的参数和自动变量。如果线程堆栈的大小太小,则可能会...
  • 堆栈以及常用的几种堆栈实现原理

    千次阅读 2012-02-27 16:32:45
    堆栈是一种数据结构,按先进后出(First In Last Out,FILO)的方式工作,使用一个称作堆栈指针的专用寄存器指示前的操作位置,堆栈指针总是指向栈顶。 1、递增堆栈:向高地址方向生长 2、递减堆栈:向低地址...
  • 另类堆栈

    千次阅读 2017-06-23 21:55:43
    习题3.14 另类堆栈 (15分) 在栈的顺序存储实现中,另有一种方法是将Top定义为栈顶的上一个位置。请编写程序实现这种定义下堆栈的入栈、出栈操作。如何判断堆栈为空或者满? 函数接口定义: bool Push( ...
  • Java 堆栈详解

    千次阅读 2019-02-18 11:06:17
    java堆内存:是存放对象本身,不存放对象的引用也不存放基本数据类型,jvm中只有一个堆(heap)所有线程共享。 java栈内存:用来存放局部变量(方法...堆栈溢出 堆溢出,不断的创建新的 对象,没有及时回收导致堆溢...
  • //整数拆分时需要用到的堆栈 int sumStack[MAX_INTEGER]; //各个加数的和的堆栈 int numStack[MAX_INTEGER]; //各个加数的堆栈 int top; //栈顶 int nn; int ii; while ( 1==1 ) { ...
  • 堆栈的使用

    千次阅读 2012-10-17 00:52:42
    大年初七回到学习开始复习算法,重新看了这个堆栈的代码,实在不明白为什么这么多人会踩,感觉链栈实现的不错啊,增加一个顺序栈ac的代码,希望大家评价的时候真的是看了我的代码,写的不好可以留言指导我 ...
  • 堆栈的实现

    千次阅读 2015-05-07 23:55:17
    堆栈,是一种数据结构,其插入和删除操作都在同一端进行,其中一端称作栈顶,另外一端称作栈底。其中,堆栈是一种先进后出的数据结构,既可以使用公式化描述实现,也可以使用链表描述进行实现。例如,我们向栈中插入...

空空如也

1 2 3 4 5 ... 20
收藏数 69,744
精华内容 27,897
关键字:

堆栈