精华内容
下载资源
问答
  • 堆栈

    2021-02-24 16:47:05
    堆栈介绍 堆栈(stack),是数据结构的一种,特点...这也是为什么栈操作受限的原因。 栈的操作: 只有两种:push和pop ,push(压入) 表示往栈中插入数据,也入栈。 pop(弹出) 表示从栈中删除数据。也叫做出栈。 栈的实

    堆栈介绍

    堆栈(stack),是数据结构的一种,特点是先进后出、后进先出。他也是一种操作受限的线性表。
    在这里插入图片描述
    在使用的时候,可以把它想象为家里面的盘子,洗刷过后放在最上面的都是要先拿出来使用的。也就是说最后放进去的要先拿出来。然后再依次拿里面内部的。这就是后进先出的原则。

    栈是线性的,虽然拥有两个端,但是只允许在一个端进行操作进和出。这也是为什么栈操作受限的原因。

    栈的操作:

    只有两种:pushpop ,push(压入) 表示往栈中插入数据,也叫入栈。 pop(弹出) 表示从栈中删除数据。也叫做出栈。

    栈的实现

    1. 可以使用数组
    2. 可以使用链表

    栈的大小

    栈的大小随时都可以改变,栈的空间大小不可变。

    顺序栈

    用数组实现的栈。
    顺序栈的实现非常简单。先初始化一个数组,然后再用一个变量给这个数组里的元素进行计数,当有新元素需要入栈的时候,将这个新元素写入到数组的最后一个元素的后面,然后计数器加一。当需要做出栈操作时,将数组中最后一个元素返回,计数器减一。

    代码实现

    package com.example.oauth_learn;
    
    public class Test {
    
        /**
         * 用数组实现栈,最主要的是要在类的内部定义一个数组,
         * 并且这个数组要具有一定的大小,要在定义栈的时候定义好
         */
    
            private static final String TAG = "ArrayStack";
            private Object[] contents;
            private int top = -1;
            private int bottom = -1;
            private int SIZE = 10;//有一个初始值大小
    // 构造函数
            public Test()
            {
                contents = new Object[SIZE];
                top = -1;
            }
    // 入栈操作
            public int push(Object obj) throws Exception
            {
                if (top > SIZE) throw new Exception("栈已经满了!");
                top++;
                contents[top] = obj;
                return top;
            }
    // 出栈操作
            public Object pop() throws Exception
            {
                if (top == bottom) throw new Exception("栈已经空了!");
                Object obj = contents[top];
                contents[top] = null;
                top--;
                return obj;
            }
    
            public boolean isEmpty()
            {
                return top == bottom;
            }
    
            public int getSize()
            {
                return top + 1;
            }
    
            public void display() throws Exception
            {
                if (getSize() == 0) throw new Exception("空栈!");
                for (int i=getSize()-1;i>=0;i--)
                {
                    System.out.print(contents[i].toString() + "->");
                }
                System.out.println("");
            }
    
            public static void main(String[] args) throws Exception
            {
                Test as = new Test();
                //as.display();
                as.push("你好");
                as.push("q");
                as.push("werewrwer");
                as.push("weee");
                as.push("we123");
                as.push("ertte");
                as.push("ggmt");
                as.display();
                as.pop();
                System.out.println(as.getSize());
                as.pop();
                as.display();
    
            }
    
    
        }
    
    
    

    在顺序栈里面,入栈之前需要先判断栈是否满了,如果数组大小等于计数器大小,则表示已经满了。然后在入栈的时候需要把这个新元素写到数组的最后一个元素后面,然后计数器加一。需要进行出栈的时候则把最后一个元素返回,计数器减一。出栈的时候也要进行判断数组是不是空数组,如果计数器是0则表示是空数组。

    链式栈

    实现思路:

    实现思路是先定义一个链表节点的类,基于这个类去定义一个头节点Head。当有新元素需要入栈的时候,将这个新元素的Next指针指向头结点Head的Next节点,然后再将Head的Next指向这个新节点。当需要做出栈操作时,直接将Head所指向的节点返回,同时让Head指向下一个节点。
    当然,在入栈和出栈时都需要判断链表是否为空的情况。
    链式栈的入栈和出栈都是在处理头部节点,所以操作很简单,其时间和空间复杂度均为O(1)。

    代码实现:

    package com.ietree.basic.datastructure.stack;
    
    /**
     * 链栈
     *
     * Created by ietree
     * 2017/4/29
     */
    public class LinkStack<T> {
    
        // 定义一个内部类Node,Node实例代表链栈的节点
        private class Node {
    
            // 保存节点的数据
            private T data;
            // 指向下个节点的引用
            private Node next;
            // 无参构造器
            public Node() {
            }
            // 初始化全部属性的构造器
            public Node(T data, Node next) {
    
                this.data = data;
                this.next = next;
    
            }
    
        }
        // 保存该链栈的栈顶元素
        private Node top;
        // 保存该链栈中已包含的节点数
        private int size;
        // 创建空链栈
        public LinkStack() {
            // 空链栈,top的值为null
            top = null;
    
        }
    
        // 以指定数据元素来创建链栈,该链栈只有一个元素
        public LinkStack(T element) {
    
            top = new Node(element, null);
            size++;
    
        }
    
        // 返回链栈的长度
        public int length() {
    
            return size;
    
        }
    
        // 进栈
        public void push(T element) {
    
            // 让top指向新创建的元素,新元素的next引用指向原来的栈顶元素
            top = new Node(element, top);
            size++;
    
        }
    
        // 出栈
        public T pop() {
    
            Node oldTop = top;
            // 让top引用指向原栈顶元素的下一个元素
            top = top.next;
            // 释放原栈顶元素的next引用
            oldTop.next = null;
            size--;
            return oldTop.data;
    
        }
    
        // 访问栈顶元素,但不删除栈顶元素
        public T peek(){
    
            return top.data;
    
        }
    
        // 判断链栈是否为空栈
        public boolean empty() {
    
            return size == 0;
    
        }
    
        // 请空链栈
        public void clear() {
    
            top = null;
            size = 0;
    
        }
    
        public String toString() {
    
            // 链栈为空栈时
            if (empty()) {
    
                return "[]";
    
            } else {
    
                StringBuilder sb = new StringBuilder("[");
                for (Node current = top; current != null; current = current.next) {
    
                    sb.append(current.data.toString() + ", ");
    
                }
    
                int len = sb.length();
                return sb.delete(len - 2, len).append("]").toString();
            }
    
        }
    
    }
    

    然后测试使用

    package com.ietree.basic.datastructure.stack;
    
    /**
     * Created by ietree
     * 2017/4/29
     */
    public class LinkStackTest {
    
        public static void main(String[] args) {
    
            LinkStack<String> stack = new LinkStack<String>();
    
            stack.push("aaaa");
            stack.push("bbbb");
            stack.push("cccc");
            stack.push("dddd");
            System.out.println(stack);
    
            System.out.println("访问栈顶元素:" + stack.peek());
    
            System.out.println("第一次弹出栈顶元素:" + stack.pop());
    
            System.out.println("第二次弹出栈顶元素:" + stack.pop());
    
            System.out.println("两次pop之后的栈:" + stack);
    
        }
    
    }
    
    展开全文
  • 每个进程都有自己的内存堆栈区域吗,以及堆内存为什么要程序员自己释放 第一个问题回答只有一个字“是”,建议你看一本书《程序员的自我修养》。 第二个问题:对SP寄存器的值进行操作而形成逻辑上的栈,而局部变量...

    每个进程都有自己的内存堆栈区域吗,以及堆内存为什么要程序员自己释放

    第一个问题回答只有一个字“是”,建议你看一本书叫《程序员的自我修养》。
    第二个问题:对SP寄存器的值进行操作而形成逻辑上的栈,而局部变量是在函数内部定义的,就是在栈上定义的,函数的调用和对栈的操作这是一个很基础的也是很重要的知识点,你把局部变量的释放理解成了一个单独的动作,事实上编译器没有对这个局部变量的空间做任何内存管理意义上的操作。只是一个简单的对SP寄存器的值的一个改变即形成了栈的恢复动作。栈一恢复了,那之前那段栈内存上的数据你肯定找不到了,但那个物理内存地址上的数据却还是原状,所以我建义你把 ”自动释放局部变量“ 这几个字改成“自动丢弃局部变量”,丢了的东西就是找不回了,你没法用了,但那东西不会凭空从地球上消失,只是从你的视野里消失了,可能别人捡到了,别人就能用得着了,就像在函数A里创建的局部变量 local_a 可能在进程的地址空间里是地址0X11,但函数A返回之后,可能主程序又要调用函数B,而在函数B里创建的局部变量 local_b 也可能就是在0X11这个地址,那么地址0X11上边的值从A函数结束到B函数开始这段时间一直没变,只是在这段时间里没有人管理它的值。而这个过程就叫释放,或叫丢弃,
    对堆内存的操作实际是动态内存操作,就涉及到内存管理了,其实现在的操作系统内核对用户空间的进程这块的创建与注销都加入了内存保护,你在用户空间的程序中释不释放堆内存,系统都会在这个程序结束时做内存回收动作,但这仅限于用户空间的程序,如果是内核编程的话,就一定要严格释放掉动态分配的内存,否则造成系统内存泄漏,内存泄漏的后果就是可用内存被你人为的弄成了不可用内存,到最后导至系统无动态内存可分配,就无法加载程序。
    对于你的提问,其实没有办法回答得让你理解透澈,你现在对程序的运行机制和操作系统原理基本上是一个零的认识,慢慢来吧,多看操作系统原理的书,其实用户程序都是基于操作系统编程,理解一些原理性的东西是非常重要的。

    上面部分来自

    展开全文
  • 总的来说呢,它们都是数据...而栈又堆栈”,是一种使用堆的“方法”,遵循后进先出,先进后出的原则,像水桶一样。栈是在进行一个进程是其建立的存储区域。 二者区别 空间分配 栈一般由操作系统自动分配释放...

    总的来说呢,它们都是数据结构,只能在一端对数据进行操作,比如删除插入啊。不同的是:
    堆呢顺序是随意的,可以看作一棵树的数组对象,是一颗完全二叉树(也是一种数据结构,节点做多有两个子树),是在程序运行时开辟一块动态内存空间。
    而栈又叫“堆栈”,是一种使用堆的“方法”,遵循后进先出,先进后出的原则,像水桶一样。栈是在进行一个进程是为其建立的存储区域。

    二者区别

    1. 空间分配
      栈一般由操作系统自动分配释放,用来存放–函数的参数值、变量的值。
      堆由程序员分配释放,若不释放会由OS回收。
    2. 缓存方式
      栈一级缓存,被调用时处于存储空间,调用完立即释放。
      堆二级缓存,由虚拟机垃圾回收算法决定,速度相对慢一些。

    队列

    是一种特殊的线性表,和线性表相比特殊,它只能在表的前端进行删除操作,在后端进行插入。和栈的意义一样,都是操作受限制的线性表。
    建立顺序队列,需申请一片连续的储存空间,需要设置两个指针,一个指向头,一个指向尾。

    熟读就能找到区别了。。。。。

    展开全文
  • c语言中堆栈认识汇总

    2012-03-10 22:23:40
    2.为什么c语言在执行工作时程序将使用一个运行时堆栈在中国一些老师或一些低劣质量的书,喜欢把栈叫堆栈。其实堆,栈是栈。c语言在执行工作时程序将使用一个运行时堆栈,其实C语言是基于过程的语言,又叫基于函数的...

    1.堆是是不连续的内存区域,栈是是一块连续的内存的区域(有待考证)


    2.为什么c语言在执行工作时程序将使用一个运行时堆栈在中国一些老师或一些低劣质量的书,喜欢把栈叫堆栈。其实堆,栈是栈。c语言在执行工作时程序将使用一个运行时堆栈,其实C语言是基于过程的语言,又叫基于函数的语言。而函数的调用过程用栈又非常的合适。所以,伴随程序的运行,函数的调用都默认给一个栈,基本上是一个线程就有一个调用栈。C++,C#,JAVA,都一个道理。


    3.要在函数B里面调用函数A应该怎么做?是不是应该先将B的当前状态保存下来,然后再将A的数据装进来,等A处理完了以后,再将A的数据清除,最后将B的状态恢复...其实这个过程就是一个栈的结构,先将压栈的顺序是 B的状态->A的数据,出栈顺序相反 A的数据->B的状态。这不就和上面的处理过程一致吗?当然,你使用其他的方法也是可以的,但是栈的操作要简单许多,压栈和出栈只需要移动头指针就可以了。


    4.学过汇编语言吗?如果学过的话就很好解释啦,不过也没事,其实你问的问题是涉及到C的底层工作机制的,C的底层就是汇编,我们举一个例子,pirntf("%d %d",a,b);这个函数的实现机制是什么呢?首先这个函数有三个参数,在执行此函数时,会将此函数的三个参数压入栈中(sp指针会一直指向栈顶元素的),那么函数就会对这些数据进行处理(因为就在栈中,很容易找到数据的位置,这些不是你做的,是编译器替你完成的),如果函数调用完成,则sp就会恢复到函数调用前的位置,也就是我们说的数据被释放啦,其他函数也是如此。比如:
    int add(int x,int y)
    {
      int z;
      z = x + y;
      return z;
    }

    只是在栈中又开辟了z的空间,函数调用后会自动释放的。这就是我们经常说的局部变量,如果想深入理解他的汇编级是怎么实现的,请用command下debug -u 进行反汇编,找到汇编代码仔细研究。堆就是函数动态分配的空间,比如malloc();分配的空间都是在堆里面,我所讲的都是在DOS下,windows下会稍微复杂一些,基本原理都一样。


    5.简单点,为什么需要栈? 栈是一种数据结构,无论是程序还是计算机内部,都大量地用到栈这种数据结构。如函数的调用,需要用栈来维护,这样使得程序运行更容易维护,更加效率。堆,最大的特点就是在程序运行时可动态申请内存


    6.LZ只的是调用栈吧,它是用来描述函数之间的调用关系的,调用栈有stack frame组成,每一个stack frame对应着一个为运行完的函数


    7.堆 heap 栈 stack  堆栈这种说法是不严格的,尽量别用这种说法。
    为什么要用堆栈?这样可以更好的利用内存空间。(之前的内存是非常的宝贵的) 栈可以帮助程序员管理一小部分的内存(局部变量等退出函数后就销毁了)。而堆即是供程序员支配管理的。这样就很灵活了,又不会令程序员太累,又给程序员发挥的空间。而且两者增长方向刚好相反,栈是从高地址到低地址,堆是从低地址到高地址。这样空间利用的很充分。


    8.C语言的局部变量和参数传递都需要大量使用堆栈。在一个程序顺序中,大函数调用小函数需要向栈压入其所需要的参数,所以就要改变堆栈内容。多线程的程序运行期间不同的线程中其所使用的内存数据也不相同,如果还使用同一个栈的话,那么参数势必会发生混乱,如果使用静态堆栈,那么所有的代码都需要基于一个固定的地址来做堆栈操作,函数中想使用堆栈就全部需要按绝对地址定位,这样非常非常不方便。
    对于多线程来说,每一个线程都需要一个栈,所以堆栈是创建线程的时候动态分配的。单线程进程与多线程进程并没有本质的区别,它们都是一个进程中包含1~N个线程的形式,所以单线程进程的堆栈也是在创建该进程的主线程时是为其主线程分配的。
    程序中使用栈结构是因为它可以很方便地管理一个模块内所需要使用的内存。在堆栈平衡原则的约束下,一个顺序执行中各个模块在执行的时候都拥有一个堆栈空间,当它运行完毕后只要将esp掉正回调用它时的那个样子那么它对调用者就不会有任何破坏左右。程序调用的时候,因为执行完被调用的函数必须得将调用前的ip寄存器地址缓存下来才可以恢复。这些必要的临时数据都需要一个数据结构将它们保存起来而且也需要快速方便地找到。对于这种需要,老外们研究出了这种栈结构。

    因为保护模式下的windows是不允许使用野生内存的,所以程序在内存中除了文件的映射以外其它所需要的内存都是以堆或栈的形式提供出来,所以堆栈就是程序中所有动态数据所使用的内存。堆和栈各是一种数据结构,也有人喜欢把栈叫做堆栈。


    9.这个看linux内核原理就知道了,linux可运行的程序叫ELF格式,他规定了各个区域包括大家知道的 全局变量区,BSS区,代码区,等等,当然了,堆的使用也linux操作系统也是相关的,在设计OS的时候,就考虑到进程需要动态获得内存了。而栈个人感觉是C语言自己设计的,也就是说编译器自己安排的。这个观点可以见C专家编程,有一章讲述这个问题的。

    展开全文
  • 深入理解任务堆栈

    千次阅读 2009-08-30 20:28:00
    先来看这一个小函数,猜猜他的运行结果(VC6环境)?#include void b(){ int data[10]; printf("helloworld!/r/n"); data[11]-=5;}int main(){ b();...没错, 那么结果是什么呢,为什么会不停打印hellowo
  • 首先,此操作系统不MyOS了,NOS 然后这个系统是分页了的,但是并没有什么问题啊,本质上加上段起始地址,映射成分页地址,但是段...为什么要这么做?首先呢,2800000是代码起始地址,因为所有标签都是从0开始计数
  • 函数的调用堆栈 一、 什么是栈帧? 栈帧也过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。 实际上,可以简单理解:栈帧就是存储在用户栈上的(当然内核栈同样适用)每一次函数调用涉及的相关...
  • 为什么需要bootloader

    千次阅读 2016-01-21 22:13:43
    首先,bootloader的作用是在硬件商店后运行的第一段软件代码,也引导加载程序,是在操作系统内核运行之前运行的一小段程序,这小段程序的作用一般是初始化硬件设备,比如内存啊,堆栈等等,从
  • 为什么很多人C语言学不下去? 首先看什么叫学会C语言 如果只是简单的写出一些循环语句、字符处理等操作,或者按照一些示例代码完成一个跑马灯程序,那只能叫你了解这个语言。 真正的学会C语言,你要理解指针、内存、...
  • 1、虚拟机栈是什么? 栈也栈内存,是java虚拟机的内存模型之一。它的生命周期是在线程创建时创建,线程结束而消亡,释放内存。因此是私有的,不可共享 栈存储的数据,以栈帧(Stack Frame)单位存储,栈帧是一个...
  • 目录一、前言二、资料、网站和链接:三、C语言中怎么存储变量四、stack(栈)4.1、栈4.2、c什么时候用栈(stack)4.3、栈的特性:4.4、示范代码:五、heap(堆)5.1、堆的通俗说法5.2、堆的特性5.3、这里是一个...
  • 求问大佬是什么原因。 调用的子程序是闰年里的datacate,在我写的代码里mult。 我写的二变量加法的程序 <code>DATAS SEGMENT NUM1 DB 0DH,0AH,'Please enter the first number:',13,10,'$&...
  • 线程是OS(操作系统)调度CPU的最小单元,也轻量级进程(Light Weight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。CPU在这些线程上...
  • 即用来放数据的数据段DS,临时存放数据的堆栈段SS、存放程序代码的代码段、存放附加数据的附加段,每一段的最大存储空间64KB,跳转指令、程序调用指令在转移到地址没有超过64KB地址空间范围的段内转移,超出64KB...
  • python的编程使用过程中,list列表结构我想是必不可少的,这也是...什么是嵌套列表呢,简单来说就是:列表内的元素也是列表,对于这样的列表对象我一般习惯称之“嵌套列表”,当然如果只嵌套一层的话你也可以它...
  •  之前对几个没什么理解,只是简单的用过可空类型,也是知道怎么用,至于为什么,还真不太清楚,通过整理本文章学到了很多知识,也许对于以后的各种代码优化都有好处。  本文的重点就是:值类型直接存储其值,...
  • 线程简介什么是线程现代操作系统调度的最小单元是线程,也轻量级进程(Light Weight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。...
  • 数据结构第三章栈.ppt

    2020-01-13 00:06:44
    定义: Q1堆栈是什么它与一般线性表有什么不同 Q2顺序表和顺序栈的操作有何区别 Q3什么叫向上生成的栈 向下生成又是何意 Q4为什么要设计堆栈它有什么独特用途 例2:一个栈的输入序列为1,2,3若在入栈的过程中允许出栈...
  • 随想随记第一

    2011-07-31 23:43:31
    第二个问题,为什么要有堆栈 堆栈不是从来就有的 当初老冯只是说要有个放代码和数据的地方,名气也取好了,存储器,然后他就翘了。至于后来存储器由于受曝光率很高的“客观因素”影响,分了内外,算不算他...
  • C#中的内存分配

    千次阅读 2015-04-01 22:49:11
    虚拟内存中存在一个叫堆栈的区域,我们并不知道它到底在地址空间的什么地方,在一般开发过程中也没有必要知道,我们知道的是值类型就分配于此。值类型在堆栈上分配的时候,是自上而下填充的,也就是从高内存地址开始...
  • 2.为什么c语言在执行工作时程序将使用一个运行时堆栈在中国一些老师或一些低劣质量的书,喜欢把栈叫堆栈。其实堆,栈是栈。c语言在执行工作时程序将使用一个运行时堆栈,其实C语言是基于过程的语言,又叫基于函数的...
  • 5.1 为什么要编码 217 5.2 简单的编码——异或大法 221 5.3 简便的变形——微调法 231 5.4 直接替换法 233 5.5 字符拆分法 239 5.6 内存搜索法 247 5.7 搜索实例——Serv_U漏洞的利用 249 5.8 “计算与你同行”—— ...
  • C#基础补充

    2020-07-22 10:49:57
    虚拟内存中存在一个叫堆栈的区域,我们并不知道它到底在地址空间的什么地方,在一般开发过程中也没有必要知道,我们知道的是值类型就分配于此。值类型在堆栈上分配的时候,是自上而下填充的,也就是从高内存地址开始...
  • 为什么叫托管堆,我们往下看。 栈:就是堆栈,因为和堆一起叫着别扭,就简称栈了。后进先出 托管堆不同于堆,它是由CLR(公共语言运行库(Common Language Runtime))管理,当堆中满了之后,会自动清理堆中的垃圾。...
  • 对堆和栈的一点思考

    2016-11-05 23:22:53
    首先,讲讲栈吧,栈又叫堆栈,具体为什么这么叫,我不清楚,但是,至少有点意思的地方是这个名字刚好是这两个东西单名的结合。 栈的话,通常都是程序用于保存临时数据的地方,比如一些函数内部申明的变量,函数调用...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 241
精华内容 96
关键字:

为什么叫堆栈