队列与栈 #
一、Queue队列 #
1.1 队列特点 #
- 先进先出(FIFO)
- 入队Enqueue,出队Dequeue
- 查看队首Peek
1.2 创建队列 #
csharp
var queue1 = new Queue<int>();
var queue2 = new Queue<int>(10);
var queue3 = new Queue<int>(new[] { 1, 2, 3, 4, 5 });
1.3 入队与出队 #
csharp
var queue = new Queue<string>();
queue.Enqueue("第一个");
queue.Enqueue("第二个");
queue.Enqueue("第三个");
string first = queue.Dequeue();
string second = queue.Dequeue();
1.4 查看队首 #
csharp
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
int front = queue.Peek();
int count = queue.Count;
1.5 其他操作 #
csharp
var queue = new Queue<int>(new[] { 1, 2, 3, 4, 5 });
bool contains = queue.Contains(3);
int[] array = queue.ToArray();
queue.Clear();
1.6 遍历队列 #
csharp
var queue = new Queue<string>();
queue.Enqueue("张三");
queue.Enqueue("李四");
queue.Enqueue("王五");
foreach (var item in queue)
{
Console.WriteLine(item);
}
二、Stack栈 #
2.1 栈特点 #
- 后进先出(LIFO)
- 入栈Push,出栈Pop
- 查看栈顶Peek
2.2 创建栈 #
csharp
var stack1 = new Stack<int>();
var stack2 = new Stack<int>(10);
var stack3 = new Stack<int>(new[] { 1, 2, 3, 4, 5 });
2.3 入栈与出栈 #
csharp
var stack = new Stack<string>();
stack.Push("第一个");
stack.Push("第二个");
stack.Push("第三个");
string top1 = stack.Pop();
string top2 = stack.Pop();
2.4 查看栈顶 #
csharp
var stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int top = stack.Peek();
int count = stack.Count;
2.5 其他操作 #
csharp
var stack = new Stack<int>(new[] { 1, 2, 3, 4, 5 });
bool contains = stack.Contains(3);
int[] array = stack.ToArray();
stack.Clear();
2.6 遍历栈 #
csharp
var stack = new Stack<string>();
stack.Push("张三");
stack.Push("李四");
stack.Push("王五");
foreach (var item in stack)
{
Console.WriteLine(item);
}
三、PriorityQueue优先队列(.NET 6+) #
3.1 创建优先队列 #
csharp
var pq = new PriorityQueue<string, int>();
pq.Enqueue("低优先级", 3);
pq.Enqueue("高优先级", 1);
pq.Enqueue("中优先级", 2);
string highest = pq.Dequeue();
string next = pq.Dequeue();
3.2 自定义优先级 #
csharp
public class Task
{
public string Name { get; set; }
public int Priority { get; set; }
}
var pq = new PriorityQueue<Task, int>();
pq.Enqueue(new Task { Name = "任务A", Priority = 3 }, 3);
pq.Enqueue(new Task { Name = "任务B", Priority = 1 }, 1);
pq.Enqueue(new Task { Name = "任务C", Priority = 2 }, 2);
while (pq.Count > 0)
{
var task = pq.Dequeue();
Console.WriteLine($"{task.Name}: 优先级{task.Priority}");
}
四、实战示例 #
4.1 消息队列 #
csharp
public class MessageQueue
{
private readonly Queue<Message> _queue = new();
private readonly object _lock = new();
public void Send(Message message)
{
lock (_lock)
{
_queue.Enqueue(message);
Monitor.Pulse(_lock);
}
}
public Message Receive()
{
lock (_lock)
{
while (_queue.Count == 0)
{
Monitor.Wait(_lock);
}
return _queue.Dequeue();
}
}
public int Count
{
get { lock (_lock) { return _queue.Count; } }
}
}
public record Message(string Content, DateTime Timestamp);
4.2 任务调度 #
csharp
public class TaskScheduler
{
private readonly PriorityQueue<Task, DateTime> _tasks = new();
public void Schedule(Task task, DateTime executeAt)
{
_tasks.Enqueue(task, executeAt);
}
public void Schedule(Task task, TimeSpan delay)
{
Schedule(task, DateTime.Now.Add(delay));
}
public async Task RunAsync(CancellationToken cancellationToken = default)
{
while (!cancellationToken.IsCancellationRequested)
{
if (_tasks.TryPeek(out _, out var executeAt))
{
var delay = executeAt - DateTime.Now;
if (delay <= TimeSpan.Zero)
{
var task = _tasks.Dequeue();
await ExecuteTaskAsync(task);
}
else
{
await Task.Delay(delay, cancellationToken);
}
}
else
{
await Task.Delay(100, cancellationToken);
}
}
}
private async Task ExecuteTaskAsync(Task task)
{
Console.WriteLine($"执行任务:{task.Name}");
await Task.CompletedTask;
}
}
4.3 表达式求值 #
csharp
public static class ExpressionEvaluator
{
public static double Evaluate(string expression)
{
var values = new Stack<double>();
var operators = new Stack<char>();
for (int i = 0; i < expression.Length; i++)
{
char c = expression[i];
if (char.IsDigit(c))
{
double num = 0;
while (i < expression.Length && char.IsDigit(expression[i]))
{
num = num * 10 + (expression[i] - '0');
i++;
}
i--;
values.Push(num);
}
else if (c == '(')
{
operators.Push(c);
}
else if (c == ')')
{
while (operators.Peek() != '(')
{
values.Push(ApplyOperator(operators.Pop(), values.Pop(), values.Pop()));
}
operators.Pop();
}
else if (IsOperator(c))
{
while (operators.Count > 0 && Precedence(operators.Peek()) >= Precedence(c))
{
values.Push(ApplyOperator(operators.Pop(), values.Pop(), values.Pop()));
}
operators.Push(c);
}
}
while (operators.Count > 0)
{
values.Push(ApplyOperator(operators.Pop(), values.Pop(), values.Pop()));
}
return values.Pop();
}
private static bool IsOperator(char c) => c == '+' || c == '-' || c == '*' || c == '/';
private static int Precedence(char op) => op switch
{
'+' or '-' => 1,
'*' or '/' => 2,
_ => 0
};
private static double ApplyOperator(char op, double b, double a) => op switch
{
'+' => a + b,
'-' => a - b,
'*' => a * b,
'/' => a / b,
_ => throw new ArgumentException($"未知运算符:{op}")
};
}
4.4 浏览器历史记录 #
csharp
public class BrowserHistory
{
private readonly Stack<string> _backStack = new();
private readonly Stack<string> _forwardStack = new();
private string _current;
public void Visit(string url)
{
if (_current != null)
{
_backStack.Push(_current);
}
_current = url;
_forwardStack.Clear();
}
public string Back()
{
if (_backStack.Count == 0)
return null;
_forwardStack.Push(_current);
_current = _backStack.Pop();
return _current;
}
public string Forward()
{
if (_forwardStack.Count == 0)
return null;
_backStack.Push(_current);
_current = _forwardStack.Pop();
return _current;
}
public string Current => _current;
public bool CanGoBack => _backStack.Count > 0;
public bool CanGoForward => _forwardStack.Count > 0;
}
五、性能对比 #
| 操作 | Queue | Stack | List |
|---|---|---|---|
| 添加 | O(1) | O(1) | O(1) |
| 删除 | O(1) | O(1) | O(n) |
| 查找 | O(n) | O(n) | O(n) |
六、总结 #
队列与栈要点:
| 数据结构 | 特点 | 主要方法 |
|---|---|---|
| Queue |
FIFO | Enqueue, Dequeue, Peek |
| Stack |
LIFO | Push, Pop, Peek |
| PriorityQueue | 优先级 | Enqueue, Dequeue, Peek |
下一步,让我们学习异常处理!
最后更新:2026-03-26