🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
数据结构是计算机科学中的一个重要概念,它描述了数据之间的组织方式和关系,以及对这些数据的访问和操作。常见的数据结构有:数组、链表、栈、队列、哈希表、树、堆和图。
栈是一种数据结构,它基于后进先出的原则,也被称为LIFO(Last In First Out)结构。栈可以用来表示任何具有“一端进、一端出”的数据结构。它包括两个基本操作:入栈(push)和出栈(pop)。
栈的基本思想是,数据元素按照后进先出的顺序插入和删除,插入和删除元素只能在栈顶进行。当有新元素插入时,它就成为了新的栈顶元素,当元素被删除时,栈顶元素被移除,下一个元素成为新的栈顶元素。
栈可以使用数组或链表实现。使用数组实现的栈被称为顺序栈,使用链表实现的栈被称为链式栈。在实现栈的过程中,需要注意栈空间的管理,包括栈的空间分配和释放等问题。
以下是C#中栈(Stack)常用操作及示例:
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int result = stack.Pop(); // result 的值为 2
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int result = stack.Peek(); // result 的值为 2,但栈中依然有 2
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int count = stack.Count; // count 的值为 2
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Clear(); // 栈中没有元素了
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
bool contains = stack.Contains(2); // contains 的值为 true
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int[] array = new int[stack.Count];
stack.CopyTo(array, 0); // array 的值为 {2, 1}
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.TrimExcess(); // 优化内存使用
图解:
示例:
// === File: linkedlist_stack.cs ===
/* 基于链表实现的栈 */
class LinkedListStack {
private ListNode? stackPeek; // 将头节点作为栈顶
private int stkSize = 0; // 栈的长度
public LinkedListStack() {
stackPeek = null;
}
/* 获取栈的长度 */
public int size() {
return stkSize;
}
/* 判断栈是否为空 */
public bool isEmpty() {
return size() == 0;
}
/* 入栈 */
public void push(int num) {
ListNode node = new ListNode(num);
node.next = stackPeek;
stackPeek = node;
stkSize++;
}
/* 出栈 */
public int pop() {
if (stackPeek == null)
throw new Exception();
int num = peek();
stackPeek = stackPeek.next;
stkSize--;
return num;
}
/* 访问栈顶元素 */
public int peek() {
if (size() == 0 || stackPeek == null)
throw new Exception();
return stackPeek.val;
}
/* 将 List 转化为 Array 并返回 */
public int[] toArray() {
if (stackPeek == null)
return Array.Empty<int>();
ListNode node = stackPeek;
int[] res = new int[size()];
for (int i = res.Length - 1; i >= 0; i--) {
res[i] = node.val;
node = node.next;
}
return res;
}
}
在链表实现中,链表的扩容非常灵活,不存在数组扩容时效率降低的问题。但是,入栈操作需要初始化节点对象并修改指针,因此效率相对较低。不过,如果入栈元素本身就是节点对象,那么可以省去初始化步骤,从而提高效率。
图解:
示例:
/* 基于数组实现的栈 */
class ArrayStack {
private List<int> stack;
public ArrayStack() {
// 初始化列表(动态数组)
stack = new();
}
/* 获取栈的长度 */
public int size() {
return stack.Count();
}
/* 判断栈是否为空 */
public bool isEmpty() {
return size() == 0;
}
/* 入栈 */
public void push(int num) {
stack.Add(num);
}
/* 出栈 */
public int pop() {
if (isEmpty())
throw new Exception();
var val = peek();
stack.RemoveAt(size() - 1);
return val;
}
/* 访问栈顶元素 */
public int peek() {
if (isEmpty())
throw new Exception();
return stack[size() - 1];
}
/* 将 List 转化为 Array 并返回 */
public int[] toArray() {
return stack.ToArray();
}
}
数组实现额外支持随机访问,但这已超出了栈的定义范畴,因此一般不会用到。
在基于数组的实现中,入栈和出栈操作都是在预先分配好的连续内存中进行,具有很好的缓存本地性,因此效率较高。然而,如果入栈时超出数组容量,会触发扩容机制,导致该次入栈操作的时间复杂度变为 𝑂(𝑛)。
栈是一种常见的数据结构,在程序设计中广泛使用。它有以下优点和缺点:
优点:
缺点:
在使用栈时,应该根据实际需求来选择,权衡其优缺点,选择最适合的数据结构。
栈是一种数据结构,其特点是先进后出,后进先出。栈在计算机科学中有很多应用场景,其中一些包括:
1.函数调用:在编程中,每次调用函数时,系统都会将函数(及其参数和局部变量)压入栈中。当函数返回时,系统将函数从栈中弹出。
2.表达式求值:在编译器中对表达式求值时,使用栈来实现运算符优先级的处理。
3.括号匹配:在编译器中,使用栈来检测括号是否匹配,以确保代码的正确性。
4.迭代算法:在深度优先搜索(DFS)等算法中,可以使用栈来实现迭代。
5.逆序输出:可以使用栈来逆序输出数据。
6.撤销操作:许多应用程序(如文本编辑器)可以通过使用栈来支持撤销操作。
栈是一种非常有用的数据结构,在计算机科学中有很多实际应用。