From 7d55f825083ad372cab5d60a2a4cc3bb2b625401 Mon Sep 17 00:00:00 2001 From: hpstory <33348162+hpstory@users.noreply.github.com> Date: Wed, 8 Mar 2023 19:17:30 +0800 Subject: [PATCH] feature: Add csharp code array_deque and linkedlist_deque (#405) * feature: Add csharp code array_deque and linkedlist_deque * fix code style issue in comments --- .../chapter_stack_and_queue/array_deque.cs | 175 ++++++++++++++ .../linkedlist_deque.cs | 213 ++++++++++++++++++ 2 files changed, 388 insertions(+) create mode 100644 codes/csharp/chapter_stack_and_queue/array_deque.cs create mode 100644 codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs diff --git a/codes/csharp/chapter_stack_and_queue/array_deque.cs b/codes/csharp/chapter_stack_and_queue/array_deque.cs new file mode 100644 index 000000000..916af3a0c --- /dev/null +++ b/codes/csharp/chapter_stack_and_queue/array_deque.cs @@ -0,0 +1,175 @@ +/** + * File: array_deque.cs + * Created Time: 2023-03-08 + * Author: hpstory (hpstory1024@163.com) + */ + +using NUnit.Framework; + +namespace hello_algo.chapter_stack_and_queue +{ + /* 基于环形数组实现的双向队列 */ + public class ArrayDeque + { + private readonly int[] nums; // 用于存储双向队列元素的数组 + private int front; // 队首指针,指向队首元素 + private int queSize; // 双向队列长度 + + /* 构造方法 */ + public ArrayDeque(int capacity) + { + this.nums = new int[capacity]; + front = queSize = 0; + } + + /* 获取双向队列的容量 */ + public int capacity() + { + return nums.Length; + } + + /* 获取双向队列的长度 */ + public int size() + { + return queSize; + } + + /* 判断双向队列是否为空 */ + public bool isEmpty() + { + return queSize == 0; + } + + /* 计算环形数组索引 */ + private int index(int i) + { + // 通过取余操作实现数组首尾相连 + // 当 i 越过数组尾部后,回到头部 + // 当 i 越过数组头部后,回到尾部 + return (i + capacity()) % capacity(); + } + + /* 队首入队 */ + public void pushFirst(int num) + { + if (queSize == capacity()) + { + Console.WriteLine("双向队列已满"); + return; + } + // 队首指针向左移动一位 + // 通过取余操作,实现 front 越过数组头部后回到尾部 + front = index(front - 1); + // 将 num 添加至队首 + nums[front] = num; + queSize++; + } + + /* 队尾入队 */ + public void pushLast(int num) + { + if (queSize == capacity()) + { + Console.WriteLine("双向队列已满"); + return; + } + // 计算尾指针,指向队尾索引 + 1 + int rear = index(front + queSize); + // 将 num 添加至队尾 + nums[rear] = num; + queSize++; + } + + /* 队首出队 */ + public int pollFirst() + { + int num = peekFirst(); + // 队首指针向后移动一位 + front = index(front + 1); + queSize--; + return num; + } + + /* 队尾出队 */ + public int pollLast() + { + int num = peekLast(); + queSize--; + return num; + } + + /* 访问队首元素 */ + public int peekFirst() + { + if (isEmpty()) + { + throw new InvalidOperationException(); + } + return nums[front]; + } + + /* 访问队尾元素 */ + public int peekLast() + { + if (isEmpty()) + { + throw new InvalidOperationException(); + } + // 计算尾元素索引 + int last = index(front + queSize - 1); + return nums[last]; + } + + /* 返回数组用于打印 */ + public int[] toArray() + { + // 仅转换有效长度范围内的列表元素 + int[] res = new int[queSize]; + for (int i = 0, j = front; i < queSize; i++, j++) + { + res[i] = nums[index(j)]; + } + return res; + } + } + + public class array_deque + { + [Test] + public void Test() + { + /* 初始化双向队列 */ + ArrayDeque deque = new ArrayDeque(10); + deque.pushLast(3); + deque.pushLast(2); + deque.pushLast(5); + Console.WriteLine("双向队列 deque = " + string.Join(" ", deque.toArray())); + + /* 访问元素 */ + int peekFirst = deque.peekFirst(); + Console.WriteLine("队首元素 peekFirst = " + peekFirst); + int peekLast = deque.peekLast(); + Console.WriteLine("队尾元素 peekLast = " + peekLast); + + /* 元素入队 */ + deque.pushLast(4); + Console.WriteLine("元素 4 队尾入队后 deque = " + string.Join(" ", deque.toArray())); + deque.pushFirst(1); + Console.WriteLine("元素 1 队首入队后 deque = " + string.Join(" ", deque.toArray())); + + /* 元素出队 */ + int pollLast = deque.pollLast(); + Console.WriteLine("队尾出队元素 = " + pollLast + ",队尾出队后 deque = " + string.Join(" ", deque.toArray())); + int pollFirst = deque.pollFirst(); + Console.WriteLine("队首出队元素 = " + pollFirst + ",队首出队后 deque = " + string.Join(" ", deque.toArray())); + + /* 获取双向队列的长度 */ + int size = deque.size(); + Console.WriteLine("双向队列长度 size = " + size); + + /* 判断双向队列是否为空 */ + bool isEmpty = deque.isEmpty(); + Console.WriteLine("双向队列是否为空 = " + isEmpty); + } + } +} diff --git a/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs b/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs new file mode 100644 index 000000000..54a01bff7 --- /dev/null +++ b/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs @@ -0,0 +1,213 @@ +/** + * File: linkedlist_deque.cs + * Created Time: 2023-03-08 + * Author: hpstory (hpstory1024@163.com) + */ + +using NUnit.Framework; + +namespace hello_algo.chapter_stack_and_queue +{ + /* 双向链表结点 */ + public class ListNode + { + public int val; // 结点值 + public ListNode? next; // 后继结点引用(指针) + public ListNode? prev; // 前驱结点引用(指针) + + public ListNode(int val) + { + this.val = val; + prev = null; + next = null; + } + } + + /* 基于双向链表实现的双向队列 */ + public class LinkedListDeque + { + private ListNode? front, rear; // 头结点 front, 尾结点 rear + private int queSize = 0; // 双向队列的长度 + + public LinkedListDeque() + { + front = null; + rear = null; + } + + /* 获取双向队列的长度 */ + public int size() + { + return queSize; + } + + /* 判断双向队列是否为空 */ + public bool isEmpty() + { + return size() == 0; + } + + /* 入队操作 */ + private void push(int num, bool isFront) + { + ListNode node = new ListNode(num); + // 若链表为空,则令 front, rear 都指向 node + if (isEmpty()) + { + front = node; + rear = node; + } + // 队首入队操作 + else if (isFront) + { + // 将 node 添加至链表头部 + front.prev = node; + node.next = front; + front = node; // 更新头结点 + } + // 队尾入队操作 + else + { + // 将 node 添加至链表尾部 + rear.next = node; + node.prev = rear; + rear = node; // 更新尾结点 + } + + queSize++; // 更新队列长度 + } + + /* 队首入队 */ + public void pushFirst(int num) + { + push(num, true); + } + + /* 队尾入队 */ + public void pushLast(int num) + { + push(num, false); + } + + /* 出队操作 */ + private int? poll(bool isFront) + { + // 若队列为空,直接返回 null + if (isEmpty()) + { + return null; + } + + int val; + // 队首出队操作 + if (isFront) + { + val = front.val; // 暂存头结点值 + // 删除头结点 + ListNode fNext = front.next; + if (fNext != null) + { + fNext.prev = null; + front.next = null; + } + + front = fNext; // 更新头结点 + } + // 队尾出队操作 + else + { + val = rear.val; // 暂存尾结点值 + // 删除尾结点 + ListNode rPrev = rear.prev; + if (rPrev != null) + { + rPrev.next = null; + rear.prev = null; + } + + rear = rPrev; // 更新尾结点 + } + + queSize--; // 更新队列长度 + return val; + } + + /* 队首出队 */ + public int? pollFirst() + { + return poll(true); + } + + /* 队尾出队 */ + public int? pollLast() + { + return poll(false); + } + + /* 访问队首元素 */ + public int? peekFirst() + { + return isEmpty() ? null : front.val; + } + + /* 访问队尾元素 */ + public int? peekLast() + { + return isEmpty() ? null : rear.val; + } + + /* 返回数组用于打印 */ + public int[] toArray() + { + ListNode node = front; + int[] res = new int[size()]; + for (int i = 0; i < res.Length; i++) + { + res[i] = node.val; + node = node.next; + } + + return res; + } + } + + public class linkedlist_deque + { + [Test] + public void Test() + { + /* 初始化双向队列 */ + LinkedListDeque deque = new LinkedListDeque(); + deque.pushLast(3); + deque.pushLast(2); + deque.pushLast(5); + Console.WriteLine("双向队列 deque = " + string.Join(" ", deque.toArray())); + + /* 访问元素 */ + int? peekFirst = deque.peekFirst(); + Console.WriteLine("队首元素 peekFirst = " + peekFirst); + int? peekLast = deque.peekLast(); + Console.WriteLine("队尾元素 peekLast = " + peekLast); + + /* 元素入队 */ + deque.pushLast(4); + Console.WriteLine("元素 4 队尾入队后 deque = " + string.Join(" ", deque.toArray())); + deque.pushFirst(1); + Console.WriteLine("元素 1 队首入队后 deque = " + string.Join(" ", deque.toArray())); + + /* 元素出队 */ + int? pollLast = deque.pollLast(); + Console.WriteLine("队尾出队元素 = " + pollLast + ",队尾出队后 deque = " + string.Join(" ", deque.toArray())); + int? pollFirst = deque.pollFirst(); + Console.WriteLine("队首出队元素 = " + pollFirst + ",队首出队后 deque = " + string.Join(" ", deque.toArray())); + + /* 获取双向队列的长度 */ + int size = deque.size(); + Console.WriteLine("双向队列长度 size = " + size); + + /* 判断双向队列是否为空 */ + bool isEmpty = deque.isEmpty(); + Console.WriteLine("双向队列是否为空 = " + isEmpty); + } + } +}