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

4432

被折叠的 条评论
为什么被折叠?



