数据结构之栈

本文详细介绍了栈和队列两种基本数据结构的定义,包括栈的后进先出特性以及顺序和链式存储结构的实现。通过示例展示了栈的操作,如进栈、出栈和查看栈顶元素。同时,文章提到了栈在浏览器历史记录、撤销/重做操作等场景中的应用,并对比了顺序栈和链式栈的区别。此外,还提供了链式栈的实现代码,包括插入和删除节点的方法。

栈与队列的定义

是限定仅在表尾进行插入和删除操作线性表

栈(Stack)进行插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素称为空栈,由此栈又称为后进先出(LIFO)结构

进栈出栈变化形式:
栈对线性表的插入和删除的位置(空间)进行限制,但是并没有限制元素的进出的时间。

例如:依次输入3个整型元素1、2、3依次进栈,那么就会有5种排序方法
第一种:1、2、3进 然后3、2、1出 321
第二种:1进 1出 2进 2出 3进 3出 123
第三种:1进 1出 2进 2出 3进 3出 231
第四种:1进 2进 2出 1出 3进 3出 213
第五中: 1进 1出 2进 3进 3出 2出 132

栈的顺序存储结构
栈作为一个线性表,其顺序存储结构也就是线性表顺序存储的简化
创建类库,新建顺序栈

public class MySeqStack<T>//顺序栈
    {
    private MySeqList<T> list;

    public MySeqStack(int maxN)
    {
        list = new MySeqList<T>(maxN);
    }
    public void Push(T elem)
    {
        if (list.Length == list.Capacity)
            throw new OutOfMemoryException();
        list.Add(elem);
    }
    public void Pop()
    {
        if(list.Length==0)
            throw new OutOfMemoryException();
        list.delete(list.Length-1);
    }

    public T Peek()
    {
        return list[list.Length - 1];
    }
    }

引用类库中的顺序表

 public  class MySeqList<T>//顺序表
    {
        private T[] array;
        private int size=0;
        public MySeqList(int MaxN)
        {
            array = new T[MaxN];
           
        }
        public void Add(T elem)
        {
            if (size == array.Length)
            {
                throw new OutOfMemoryException();
            }
            array[size] = elem;
            size++;
        }
        public void insert(int index, T element)
        {
            if (index < 0 || index > size)
            {
                throw new IndexOutOfRangeException("超出数组实际元素范围!");
            }
            if (size >= array.Length)
            {
                resize();
            }
            for (int i = size - 1; i <= index; i--)
            {
                array[i + 1] = array[i];

            }
            array[index] = element;
            size++;
        }
        public void delete(int index)
        {
            if (index < 0 || index >= size)
            {
                throw new IndexOutOfRangeException("超出数组实际元素范围");
            }

            for (int i = index; i < size - 1; i++)
            {
                array[i] = array[i + 1];
            }
            size--;

        }
        public void print()
        {
            for (int i = 0; i < array.Length; i++)
            {
                Console.WriteLine(array[i]);
            }
        }
        public void resize()
        {
            T[] arrayNew = new T[array.Length * 2];
            System.Array.Copy(array, 0, arrayNew, 0, array.Length);
            array = arrayNew;
        }

    public int Length
    {
        get { return size; }
    }
    public int Capacity//容量
    {
        get { return array.Length; }
    }
    public int IndexOf(T elem)
    {
        for (int i = 0; i < size; i++)
        {
            if (array[i].Equals(elem))
            {
                return i;
            }
        }
        return -1;
    }
    public T GetAt(int i)
    {
        if (i < 0 || i >= size)
            throw new IndexOutOfRangeException();
        return array[i];
    }
    public void SetAt(int i, T elem)
    {
        if (i < 0 || i >= size)
        {
            throw new IndexOutOfRangeException();
        }
        array[i] = elem;
    }
    public T this[int i]
    {
        get
        {
            return GetAt(i);
        }
        set
        {
            SetAt(i, value);
        }
    }
    }

新建MySeqStack类,并引用类库

static void Main(String[] args)
        {
            MySeqStack<string> ss = new MySeqStack<string>(3);
            ss.Push("第一个元素");
            ss.Push("第二个元素");
            ss.Push("第三个元素");
            try
            {
                ss.Push("第四个元素");
                Debug.Assert(false, "栈满应抛异常");
            }
            catch(OutOfMemoryException e)
            { }
            ss.Pop();
            ss.Pop();
            ss.Pop();
            try
            {
                ss.Pop();
                Debug.Assert(false, "栈空应抛异常");
            }
            catch (OutOfMemoryException e)
            { }

            Console.WriteLine( ss.Peek());
           

            Console.ReadLine();
            
        }

栈的链式存储结构

class Node<T>
    {
        public T data;
        public Node<T> next;
      
    }

    class MyLinkedList<T>//链栈
    {
        private Node<T> head;
        private Node<T> last;
        private int size;
      

        public void Insert(int index ,T data)
        {
            if (index < 0)
                throw new IndexOutOfRangeException("数组越界");
            Node<T> insertedNode = new Node<T>();
            insertedNode.data = data;
            if (size == 0)
            {
                head = insertedNode;
            }
            else if (index == 0)
            {
                insertedNode.next = head;
                head = insertedNode;
            }
            else if (size == index)
            {
                last.next = insertedNode;
                last = insertedNode;
            }
            else
            {
                int cnt = 0;
                for (Node<T> p = head; p != null; p = p.next)
                {
                    if (cnt == index - 1)
                    {
                        insertedNode.next = p.next;
                        p.next = insertedNode;
                        return;
                    }
                }



            }

            size++;
           
        }
        public void Delete(int index)
        {
            if (index < 0 || index >= size)
            {
                throw new IndexOutOfRangeException("超出链表范围");
            }

            if (index == 0)
            {
                head = head.next;
            }
            else if (index == size - 1)
            {
                int cnt = 0;
                for (Node<T> p = head; p != null; p = p.next)
                {
                    if (cnt == index - 1)
                    {
                        p.next = null;
                        return;
                    }
                    cnt++;
                }
            }
            else
            {
                int cnt = 0;
                for (Node<T> p = head; p != null; p = p.next)
                {
                    if (cnt == index - 1)
                    {
                        p.next = p.next.next;
                        return;

                    }
                    cnt++;
                }
            }
            size--;
        }
        public void print()
        {
            for (Node<T> p = head; p != null; p = p.next)
            {
                Console.WriteLine(p.data);
            }
        }
        public T GetAt(int i)
        {
            if (i < 0)
                throw new IndexOutOfRangeException();

            int cnt = 0;
            for (Node<T> p = head; p != null; p = p.next)
            {
                if (cnt == i)
                {
                    return p.data;
                }cnt++;
            }
            throw new OutOfMemoryException();

        }
        public bool IsEmpty
        {
            get
            {
                return head == null;
            }
        }
    }
class MyLinkedStack<T>
{
    private MyLinkedList<T> list = new MyLinkedList<T>();

    public void Push(T elem)
    {
        list.Insert(0, elem);
    }
    public void Pop()
    {
        if (list.IsEmpty)
            throw new OutOfMemoryException();
        list.Delete(0);
    }

    public T Peek()
    {
        return list.GetAt(0);
    }
}
class Program
    {
        static void Main(String[] args)
        {
            MySeqStack<string> ss = new MySeqStack<string>(3);
            ss.Push("第一个元素");
            ss.Push("第二个元素");
            ss.Push("第三个元素");
          
            ss.Pop();
            ss.Pop();
        

            Console.WriteLine(ss.Peek());

            Console.ReadLine();

        }
    }

和顺序栈的区别
只有栈空没有栈满
对于链栈来说,是不需要头结点的
由于单链表有头指针,而栈顶指针也是必须的,将头指针域栈顶指针合并起来。所以要在头部进行插入与删除

栈的应用
1、浏览器进行、后退的历史记录
2、用户编辑文档是的Undo/Redo操作
3、字符串逆序
4、游戏菜单层级打开关闭
5、递归
6、四则运算表达式求值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值