zoukankan      html  css  js  c++  java
  • 栈及其在.NET FrameWork中的源码分析

    1.栈是操作限定在表的尾端进行的线性表,表尾要进行插入,删除等操作。我们把表尾称为栈顶,另一端叫做栈底。栈的操作是按照后进先出(LIFO:Last
    In First Out)或是先进后出(FILO)的原则进行的,所以也叫做LIFO表或FILO表。
    clip_image002

    2.我们将栈的几个常用操作用接口表示如下:

    public interface IStack<T>

    {

            int GetLength();

            bool IsEmpty();

            void Clear();

            void Push(T item);//入栈

            T Pop();//出栈

            T GetTop()
    }

    3.使用连续空间来存储栈中的元素我们称为顺序栈,我们就实现一个简单的顺序栈,代码如下:

    public class SeqStack<T>:IStack<T>

        {

            private int maxsize;

            private T[] data;

            private int top;

     

            public T this[int index]

            {

                get { return data[index];}

                set { data[index] = value; }

            }

     

            public int Maxsize

            {

                get { return maxsize; }

                set { maxsize = value; }

            }

            public int Top

            {

                get { return top; }

                set { top = value; }

            }

     

            public SeqStack(int size)

            {

                data = new T[size];

                maxsize = size;

                top = -1;

            }

     

            public int GetLength()

            {

                return top + 1;

            }

            public void Clear()

            {

                top = -1;

            }

            public bool IsEmpty()

            {

                if (top == -1)

                    return true;

                else

                    return false;

            }

            public bool IsFull()

            {

                if (top == maxsize - 1)

                    return true;

                else

                    return false;

            }

            public void Push(T item)

            {

                if (IsFull())

                {

                    Console.WriteLine("Stack is full");

                    return;

                }

                data[++top] = item;

            }

     

            public T Pop()

            {

                T tmp = default(T);

                if (IsEmpty())

                {

                    Console.WriteLine("Stack is empty");

                    return tmp;

                }

                tmp = data[top];

                --top;

                return tmp;

            }

            public T GetTop()

            {

                if (IsEmpty())

                {

                    Console.WriteLine("Stack is empty");

                    return default(T);

                }

                return data[top];

            }

        }

     

    4.还有一种就是链式存储,实际上就是简化的单链表,节点和单链表的节点也是一样的如下:

    public class Node<T>

        {

            private T data;

            private Node<T> next;

     

            public Node(T val, Node<T> p)

            {

                data = val;

                next = p;

            }

            public Node(Node<T> p)

            {         

                next = p;

            }

            public Node()

            {

                data = default(T);

                next = null;

            }

     

            public T Data

            {

                get { return data; }

                set { data = value; }

            }

            public Node<T> Next

            {

                get { return next; }

                set { next = value; }

            }

    }

    链栈的实现如下:

    public class LinkStack<T>:IStack<T>

        {

            public Node<T> top;

            private int num;//栈中结点个数

     

            public Node<T> Top

            {

                get { return top; }

                set { top = value; }

            }

            public int Num

            {

                get { return num; }

                set { num = value; }

            }

            public LinkStack()

            {

                top=null;

                num=0;

            }

     

            public int GetLength()

            {

                return num;

            }

            public void Clear()

            {

                top = null;

                num = 0;

            }

            public bool IsEmpty()

            {

                if ((top == null) && (num == 0))

                    return true;

                else

                    return false;

            }

            public void Push(T item)

            {

                Node<T> q = new Node<T>(item);

                if (top == null)

                    top = q;

                else

                {

                    q.Next = top;

                    top = q;

                }

                ++num;

            }

            public T Pop()

            {

                if (IsEmpty())

                {

                    Console.WriteLine("Stack is empty");

                    return default(T);

                }

                Node<T> p = top;

                top = top.Next;

                --num;

                return p.Data;

            }

            public T GetTop()

            {

                if (IsEmpty())

                {

                    Console.WriteLine("Stack is empty");

                    return default(T);

                }

                return top.Data;

            }

     

        }

    5.上面是我们实现的简单的方式,我们下面来看下。Net Framework中的实现方式。C#类库中提供了泛型和非泛型版本的Stack类,主要继承
    了IEnumerable和ICollection接口。

    我们可以使用Reflector来查看下。Net Framework的实现方式,我们主要看泛型版本Stack<T>

    public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable

    在。Net Framework中的Stack中的数据以数组形式存在,当数据空间不够时,扩大1倍空间,将数据从原有缓冲区复制到新的缓冲区中会带来O(n)的数据
    复制开销,最坏可能带来sizeof(T)*(n-1)的空间浪费。数据Push,Pop的复杂度为O(1)。

    我们来看下Push操作,当空间不够的时候会扩大一倍的空间。有数组复制的开销: public void Push(T item)

    
    

        {

            if (this._size == this._array.Length)

            {

                T[] destinationArray = new T[(this._array.Length == 0) ? 4 : (2 * this._array.Length)];

                Array.Copy(this._array, 0, destinationArray, 0, this._size);

                this._array = destinationArray;

            }

            this._array[this._size++] = item;

            this._version++;

        }

    另外在Pop的时候,可能出现Stack中只有一个元素,有数组的数据都在,这时就浪费了空间,我们可以使用提供的下面函数来释放,如果元素数小于
    当前容量的 90%,将容量设置为 Stack<(Of <(T>)>) 中的实际元素数。

    public void TrimExcess()

        {

            int num = (int) (this._array.Length * 0.9);

            if (this._size < num)

            {

                T[] destinationArray = new T[this._size];

                Array.Copy(this._array, 0, destinationArray, 0, this._size);

                this._array = destinationArray;

                this._version++;

            }

        }

    6.栈,堆区别

    栈负责保存我们的代码执行(或调用)路径,而堆则负责保存对象或者说数据。

    NET框架包含一个托管堆,所有的.NET语言在分配引用类型对象时都要使用它。像值类型这样的轻量级对象始终分配在栈中,但是所有的类实例和
    数组都被生成在一个内存池中,这个内存池就是托管堆。
    垃圾收集器的基本算法很简单:
    ● 将所有的托管内存标记为垃圾
    ● 寻找正被使用的内存块,并将他们标记为有效
    ● 释放所有没有被使用的内存块
    ● 整理堆以减少碎片

  • 相关阅读:
    python3.0与python2.0有哪些不同
    python常用内置模块,执行系统命令的模块
    06python 之基本数据类型
    python语言简介、解释器、字符编码介绍
    http协议&接口规范&接口测试入门
    基于APPIUM测试微信公众号的UI自动化测试框架(结合Allure2测试报告框架)
    SQL注入工具sqlmap的注入过程记录
    unittest框架
    测试转型之路--学习ing
    Tomcat分析-启动过程
  • 原文地址:https://www.cnblogs.com/carysun/p/Stack.html
Copyright © 2011-2022 走看看