From c2be6ebfbe038c8832044e43a1879c761e828a67 Mon Sep 17 00:00:00 2001 From: sjinzh <99076655+sjinzh@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:45:27 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80feat:=20add=20rust=20codes=20for=20?= =?UTF-8?q?array=5Fdeque=20(#418)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update zig codes style * feat: add rust codes for array_deque * Update array_deque.rs --------- Co-authored-by: Yudong Jin --- codes/rust/Cargo.toml | 5 + .../chapter_stack_and_queue/array_deque.rs | 157 ++++++++++++++++++ .../chapter_array_and_linkedlist/my_list.zig | 24 +-- codes/zig/chapter_heap/heap.zig | 38 ++--- codes/zig/chapter_heap/my_heap.zig | 56 +++---- .../chapter_stack_and_queue/array_queue.zig | 12 +- codes/zig/chapter_stack_and_queue/deque.zig | 16 +- 7 files changed, 235 insertions(+), 73 deletions(-) create mode 100644 codes/rust/chapter_stack_and_queue/array_deque.rs diff --git a/codes/rust/Cargo.toml b/codes/rust/Cargo.toml index 36819644f..65c77ed8d 100644 --- a/codes/rust/Cargo.toml +++ b/codes/rust/Cargo.toml @@ -69,6 +69,11 @@ path = "chapter_stack_and_queue/linkedlist_queue.rs" name = "deque" path = "chapter_stack_and_queue/deque.rs" +# Run Command: cargo run --bin array_deque +[[bin]] +name = "array_deque" +path = "chapter_stack_and_queue/array_deque.rs" + # Run Command: cargo run --bin linkedlist_deque [[bin]] name = "linkedlist_deque" diff --git a/codes/rust/chapter_stack_and_queue/array_deque.rs b/codes/rust/chapter_stack_and_queue/array_deque.rs new file mode 100644 index 000000000..2b9e15244 --- /dev/null +++ b/codes/rust/chapter_stack_and_queue/array_deque.rs @@ -0,0 +1,157 @@ +/* + * File: array_deque.rs + * Created Time: 2023-03-11 + * Author: sjinzh (sjinzh@gmail.com) + */ + +include!("../include/include.rs"); + +/* 基于环形数组实现的双向队列 */ +struct ArrayDeque { + nums: Vec, // 用于存储双向队列元素的数组 + front: usize, // 队首指针,指向队首元素 + que_size: usize, // 双向队列长度 +} + +impl ArrayDeque { + /* 构造方法 */ + pub fn new(capacity: usize) -> Self { + Self { + nums: vec![0; capacity], + front: 0, + que_size: 0, + } + } + + /* 获取双向队列的容量 */ + pub fn capacity(&self) -> usize { + self.nums.len() + } + + /* 获取双向队列的长度 */ + pub fn size(&self) -> usize { + self.que_size + } + + /* 判断双向队列是否为空 */ + pub fn is_empty(&self) -> bool { + self.que_size == 0 + } + + /* 计算环形数组索引 */ + fn index(&self, i: i32) -> usize { + // 通过取余操作实现数组首尾相连 + // 当 i 越过数组尾部后,回到头部 + // 当 i 越过数组头部后,回到尾部 + return ((i + self.capacity() as i32) % self.capacity() as i32) as usize; + } + + /* 队首入队 */ + pub fn push_first(&mut self, num: i32) { + if self.que_size == self.capacity() { + println!("双向队列已满"); + return + } + // 队首指针向左移动一位 + // 通过取余操作,实现 front 越过数组头部后回到尾部 + self.front = self.index(self.front as i32 - 1); + // 将 num 添加至队首 + self.nums[self.front] = num; + self.que_size += 1; + } + + /* 队尾入队 */ + pub fn push_last(&mut self, num: i32) { + if self.que_size == self.capacity() { + println!("双向队列已满"); + return + } + // 计算尾指针,指向队尾索引 + 1 + let rear = self.index(self.front as i32 + self.que_size as i32); + // 将 num 添加至队尾 + self.nums[rear] = num; + self.que_size += 1; + } + + /* 队首出队 */ + fn pop_first(&mut self) -> i32 { + let num = self.peek_first(); + // 队首指针向后移动一位 + self.front = self.index(self.front as i32 + 1); + self.que_size -= 1; + num + } + + /* 队尾出队 */ + fn pop_last(&mut self) -> i32 { + let num = self.peek_last(); + self.que_size -= 1; + num + } + + /* 访问队首元素 */ + fn peek_first(&self) -> i32 { + if self.is_empty() { panic!("双向队列为空") }; + self.nums[self.front] + } + + /* 访问队尾元素 */ + fn peek_last(&self) -> i32 { + if self.is_empty() { panic!("双向队列为空") }; + // 计算尾元素索引 + let last = self.index(self.front as i32 + self.que_size as i32 - 1); + self.nums[last] + } + + /* 返回数组用于打印 */ + fn to_array(&self) -> Vec { + // 仅转换有效长度范围内的列表元素 + let mut res = vec![0; self.que_size]; + let mut j = self.front; + for i in 0..self.que_size { + res[i] = self.nums[self.index(j as i32)]; + j += 1; + } + res + } +} + +fn main() { + /* 初始化双向队列 */ + let mut deque = ArrayDeque::new(10); + deque.push_last(3); + deque.push_last(2); + deque.push_last(5); + print!("双向队列 deque = "); + print_util::print_array(&deque.to_array()); + + /* 访问元素 */ + let peek_first = deque.peek_first(); + print!("\n队首元素 peek_first = {}", peek_first); + let peek_last = deque.peek_last(); + print!("\n队尾元素 peek_last = {}", peek_last); + + /* 元素入队 */ + deque.push_last(4); + print!("\n元素 4 队尾入队后 deque = "); + print_util::print_array(&deque.to_array()); + deque.push_first(1); + print!("\n元素 1 队首入队后 deque = "); + print_util::print_array(&deque.to_array()); + + /* 元素出队 */ + let pop_last = deque.pop_last(); + print!("\n队尾出队元素 = {},队尾出队后 deque = ", pop_last); + print_util::print_array(&deque.to_array()); + let pop_first = deque.pop_first(); + print!("\n队首出队元素 = {},队首出队后 deque = ", pop_first); + print_util::print_array(&deque.to_array()); + + /* 获取双向队列的长度 */ + let size = deque.size(); + print!("\n双向队列长度 size = {}", size); + + /* 判断双向队列是否为空 */ + let is_empty = deque.is_empty(); + print!("\n双向队列是否为空 = {}", is_empty); +} diff --git a/codes/zig/chapter_array_and_linkedlist/my_list.zig b/codes/zig/chapter_array_and_linkedlist/my_list.zig index da6a638d9..bdf76b8ff 100644 --- a/codes/zig/chapter_array_and_linkedlist/my_list.zig +++ b/codes/zig/chapter_array_and_linkedlist/my_list.zig @@ -11,9 +11,9 @@ pub fn MyList(comptime T: type) type { const Self = @This(); nums: []T = undefined, // 数组(存储列表元素) - numsCapacity: usize = 10, // 列表容量 - numSize: usize = 0, // 列表长度(即当前元素数量) - extendRatio: usize = 2, // 每次列表扩容的倍数 + nums_capacity: usize = 10, // 列表容量 + num_size: usize = 0, // 列表长度(即当前元素数量) + extend_ratio: usize = 2, // 每次列表扩容的倍数 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -23,7 +23,7 @@ pub fn MyList(comptime T: type) type { self.mem_arena = std.heap.ArenaAllocator.init(allocator); self.mem_allocator = self.mem_arena.?.allocator(); } - self.nums = try self.mem_allocator.alloc(T, self.numsCapacity); + self.nums = try self.mem_allocator.alloc(T, self.nums_capacity); std.mem.set(T, self.nums, @as(T, 0)); } @@ -35,12 +35,12 @@ pub fn MyList(comptime T: type) type { // 获取列表长度(即当前元素数量) pub fn size(self: *Self) usize { - return self.numSize; + return self.num_size; } // 获取列表容量 pub fn capacity(self: *Self) usize { - return self.numsCapacity; + return self.nums_capacity; } // 访问元素 @@ -63,7 +63,7 @@ pub fn MyList(comptime T: type) type { if (self.size() == self.capacity()) try self.extendCapacity(); self.nums[self.size()] = num; // 更新元素数量 - self.numSize += 1; + self.num_size += 1; } // 中间插入元素 @@ -78,7 +78,7 @@ pub fn MyList(comptime T: type) type { } self.nums[index] = num; // 更新元素数量 - self.numSize += 1; + self.num_size += 1; } // 删除元素 @@ -91,22 +91,22 @@ pub fn MyList(comptime T: type) type { self.nums[j] = self.nums[j + 1]; } // 更新元素数量 - self.numSize -= 1; + self.num_size -= 1; // 返回被删除元素 return num; } // 列表扩容 pub fn extendCapacity(self: *Self) !void { - // 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组 - var newCapacity = self.capacity() * self.extendRatio; + // 新建一个长度为 size * extend_ratio 的数组,并将原数组拷贝到新数组 + var newCapacity = self.capacity() * self.extend_ratio; var extend = try self.mem_allocator.alloc(T, newCapacity); std.mem.set(T, extend, @as(T, 0)); // 将原数组中的所有元素复制到新数组 std.mem.copy(T, extend, self.nums); self.nums = extend; // 更新列表容量 - self.numsCapacity = newCapacity; + self.nums_capacity = newCapacity; } // 将列表转换为数组 diff --git a/codes/zig/chapter_heap/heap.zig b/codes/zig/chapter_heap/heap.zig index ecc3fe844..20041f800 100644 --- a/codes/zig/chapter_heap/heap.zig +++ b/codes/zig/chapter_heap/heap.zig @@ -36,45 +36,45 @@ pub fn main() !void { // 初始化堆 // 初始化小顶堆 const PQlt = std.PriorityQueue(i32, void, lessThan); - var minHeap = PQlt.init(std.heap.page_allocator, {}); - defer minHeap.deinit(); + var min_heap = PQlt.init(std.heap.page_allocator, {}); + defer min_heap.deinit(); // 初始化大顶堆 const PQgt = std.PriorityQueue(i32, void, greaterThan); - var maxHeap = PQgt.init(std.heap.page_allocator, {}); - defer maxHeap.deinit(); + var max_heap = PQgt.init(std.heap.page_allocator, {}); + defer max_heap.deinit(); std.debug.print("\n以下测试样例为大顶堆", .{}); // 元素入堆 - try testPush(i32, mem_allocator, &maxHeap, 1); - try testPush(i32, mem_allocator, &maxHeap, 3); - try testPush(i32, mem_allocator, &maxHeap, 2); - try testPush(i32, mem_allocator, &maxHeap, 5); - try testPush(i32, mem_allocator, &maxHeap, 4); + try testPush(i32, mem_allocator, &max_heap, 1); + try testPush(i32, mem_allocator, &max_heap, 3); + try testPush(i32, mem_allocator, &max_heap, 2); + try testPush(i32, mem_allocator, &max_heap, 5); + try testPush(i32, mem_allocator, &max_heap, 4); // 获取堆顶元素 - var peek = maxHeap.peek().?; + var peek = max_heap.peek().?; std.debug.print("\n堆顶元素为 {}\n", .{peek}); // 堆顶元素出堆 - try testPop(i32, mem_allocator, &maxHeap); - try testPop(i32, mem_allocator, &maxHeap); - try testPop(i32, mem_allocator, &maxHeap); - try testPop(i32, mem_allocator, &maxHeap); - try testPop(i32, mem_allocator, &maxHeap); + try testPop(i32, mem_allocator, &max_heap); + try testPop(i32, mem_allocator, &max_heap); + try testPop(i32, mem_allocator, &max_heap); + try testPop(i32, mem_allocator, &max_heap); + try testPop(i32, mem_allocator, &max_heap); // 获取堆的大小 - var size = maxHeap.len; + var size = max_heap.len; std.debug.print("\n堆元素数量为 {}\n", .{size}); // 判断堆是否为空 - var is_empty = if (maxHeap.len == 0) true else false; + var is_empty = if (max_heap.len == 0) true else false; std.debug.print("\n堆是否为空 {}\n", .{is_empty}); // 输入列表并建堆 - try minHeap.addSlice(&[_]i32{ 1, 3, 2, 5, 4 }); + try min_heap.addSlice(&[_]i32{ 1, 3, 2, 5, 4 }); std.debug.print("\n输入列表并建立小顶堆后\n", .{}); - try inc.PrintUtil.printHeap(i32, mem_allocator, minHeap); + try inc.PrintUtil.printHeap(i32, mem_allocator, min_heap); _ = try std.io.getStdIn().reader().readByte(); } \ No newline at end of file diff --git a/codes/zig/chapter_heap/my_heap.zig b/codes/zig/chapter_heap/my_heap.zig index d7115ca64..059649cc2 100644 --- a/codes/zig/chapter_heap/my_heap.zig +++ b/codes/zig/chapter_heap/my_heap.zig @@ -10,14 +10,14 @@ pub fn MaxHeap(comptime T: type) type { return struct { const Self = @This(); - maxHeap: ?std.ArrayList(T) = null, // 使用列表而非数组,这样无需考虑扩容问题 + max_heap: ?std.ArrayList(T) = null, // 使用列表而非数组,这样无需考虑扩容问题 // 构造方法,根据输入列表建堆 pub fn init(self: *Self, allocator: std.mem.Allocator, nums: []const T) !void { - if (self.maxHeap != null) return; - self.maxHeap = std.ArrayList(T).init(allocator); + if (self.max_heap != null) return; + self.max_heap = std.ArrayList(T).init(allocator); // 将列表元素原封不动添加进堆 - try self.maxHeap.?.appendSlice(nums); + try self.max_heap.?.appendSlice(nums); // 堆化除叶结点以外的其他所有结点 var i: usize = parent(self.size() - 1) + 1; while (i > 0) : (i -= 1) { @@ -27,7 +27,7 @@ pub fn MaxHeap(comptime T: type) type { // 析构方法,释放内存 pub fn deinit(self: *Self) void { - if (self.maxHeap != null) self.maxHeap.?.deinit(); + if (self.max_heap != null) self.max_heap.?.deinit(); } // 获取左子结点索引 @@ -48,16 +48,16 @@ pub fn MaxHeap(comptime T: type) type { // 交换元素 fn swap(self: *Self, i: usize, j: usize) !void { - var a = self.maxHeap.?.items[i]; - var b = self.maxHeap.?.items[j]; + var a = self.max_heap.?.items[i]; + var b = self.max_heap.?.items[j]; var tmp = a; - try self.maxHeap.?.replaceRange(i, 1, &[_]T{b}); - try self.maxHeap.?.replaceRange(j, 1, &[_]T{tmp}); + try self.max_heap.?.replaceRange(i, 1, &[_]T{b}); + try self.max_heap.?.replaceRange(j, 1, &[_]T{tmp}); } // 获取堆大小 pub fn size(self: *Self) usize { - return self.maxHeap.?.items.len; + return self.max_heap.?.items.len; } // 判断堆是否为空 @@ -67,13 +67,13 @@ pub fn MaxHeap(comptime T: type) type { // 访问堆顶元素 pub fn peek(self: *Self) T { - return self.maxHeap.?.items[0]; + return self.max_heap.?.items[0]; } // 元素入堆 pub fn push(self: *Self, val: T) !void { // 添加结点 - try self.maxHeap.?.append(val); + try self.max_heap.?.append(val); // 从底至顶堆化 try self.siftUp(self.size() - 1); } @@ -85,7 +85,7 @@ pub fn MaxHeap(comptime T: type) type { // 获取结点 i 的父结点 var p = parent(i); // 当“越过根结点”或“结点无需修复”时,结束堆化 - if (p < 0 or self.maxHeap.?.items[i] <= self.maxHeap.?.items[p]) break; + if (p < 0 or self.max_heap.?.items[i] <= self.max_heap.?.items[p]) break; // 交换两结点 try self.swap(i, p); // 循环向上堆化 @@ -100,7 +100,7 @@ pub fn MaxHeap(comptime T: type) type { // 交换根结点与最右叶结点(即交换首元素与尾元素) try self.swap(0, self.size() - 1); // 删除结点 - var val = self.maxHeap.?.pop(); + var val = self.max_heap.?.pop(); // 从顶至底堆化 try self.siftDown(0); // 返回堆顶元素 @@ -115,8 +115,8 @@ pub fn MaxHeap(comptime T: type) type { var l = left(i); var r = right(i); var ma = i; - if (l < self.size() and self.maxHeap.?.items[l] > self.maxHeap.?.items[ma]) ma = l; - if (r < self.size() and self.maxHeap.?.items[r] > self.maxHeap.?.items[ma]) ma = r; + if (l < self.size() and self.max_heap.?.items[l] > self.max_heap.?.items[ma]) ma = l; + if (r < self.size() and self.max_heap.?.items[r] > self.max_heap.?.items[ma]) ma = r; // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; // 交换两结点 @@ -140,7 +140,7 @@ pub fn MaxHeap(comptime T: type) type { const PQgt = std.PriorityQueue(T, void, greaterThan); var queue = PQgt.init(std.heap.page_allocator, {}); defer queue.deinit(); - try queue.addSlice(self.maxHeap.?.items); + try queue.addSlice(self.max_heap.?.items); try inc.PrintUtil.printHeap(T, mem_allocator, queue); } }; @@ -154,33 +154,33 @@ pub fn main() !void { const mem_allocator = mem_arena.allocator(); // 初始化大顶堆 - var maxHeap = MaxHeap(i32){}; - try maxHeap.init(std.heap.page_allocator, &[_]i32{ 9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2 }); - defer maxHeap.deinit(); + var max_heap = MaxHeap(i32){}; + try max_heap.init(std.heap.page_allocator, &[_]i32{ 9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2 }); + defer max_heap.deinit(); std.debug.print("\n输入列表并建堆后\n", .{}); - try maxHeap.print(mem_allocator); + try max_heap.print(mem_allocator); // 获取堆顶元素 - var peek = maxHeap.peek(); + var peek = max_heap.peek(); std.debug.print("\n堆顶元素为 {}\n", .{peek}); // 元素入堆 const val = 7; - try maxHeap.push(val); + try max_heap.push(val); std.debug.print("\n元素 {} 入堆后\n", .{val}); - try maxHeap.print(mem_allocator); + try max_heap.print(mem_allocator); // 堆顶元素出堆 - peek = try maxHeap.pop(); + peek = try max_heap.pop(); std.debug.print("\n堆顶元素 {} 出堆后\n", .{peek}); - try maxHeap.print(mem_allocator); + try max_heap.print(mem_allocator); // 获取堆的大小 - var size = maxHeap.size(); + var size = max_heap.size(); std.debug.print("\n堆元素数量为 {}", .{size}); // 判断堆是否为空 - var is_empty = maxHeap.isEmpty(); + var is_empty = max_heap.isEmpty(); std.debug.print("\n堆是否为空 {}\n", .{is_empty}); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_stack_and_queue/array_queue.zig b/codes/zig/chapter_stack_and_queue/array_queue.zig index 93be62ce6..bbf0d1b4c 100644 --- a/codes/zig/chapter_stack_and_queue/array_queue.zig +++ b/codes/zig/chapter_stack_and_queue/array_queue.zig @@ -13,7 +13,7 @@ pub fn ArrayQueue(comptime T: type) type { nums: []T = undefined, // 用于存储队列元素的数组 cap: usize = 0, // 队列容量 front: usize = 0, // 队首指针,指向队首元素 - queSize: usize = 0, // 尾指针,指向队尾 + 1 + que_size: usize = 0, // 尾指针,指向队尾 + 1 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -41,12 +41,12 @@ pub fn ArrayQueue(comptime T: type) type { // 获取队列的长度 pub fn size(self: *Self) usize { - return self.queSize; + return self.que_size; } // 判断队列是否为空 pub fn isEmpty(self: *Self) bool { - return self.queSize == 0; + return self.que_size == 0; } // 入队 @@ -57,10 +57,10 @@ pub fn ArrayQueue(comptime T: type) type { } // 计算尾指针,指向队尾索引 + 1 // 通过取余操作,实现 rear 越过数组尾部后回到头部 - var rear = (self.front + self.queSize) % self.capacity(); + var rear = (self.front + self.que_size) % self.capacity(); // 将 num 添加至队尾 self.nums[rear] = num; - self.queSize += 1; + self.que_size += 1; } // 出队 @@ -68,7 +68,7 @@ pub fn ArrayQueue(comptime T: type) type { var num = self.peek(); // 队首指针向后移动一位,若越过尾部则返回到数组头部 self.front = (self.front + 1) % self.capacity(); - self.queSize -= 1; + self.que_size -= 1; return num; } diff --git a/codes/zig/chapter_stack_and_queue/deque.zig b/codes/zig/chapter_stack_and_queue/deque.zig index aa9d1cc8b..deb297ca3 100644 --- a/codes/zig/chapter_stack_and_queue/deque.zig +++ b/codes/zig/chapter_stack_and_queue/deque.zig @@ -26,17 +26,17 @@ pub fn main() !void { inc.PrintUtil.printQueue(i32, deque); // 访问元素 - var peekFirst = deque.first.?.data; // 队首元素 - std.debug.print("\n队首元素 peekFirst = {}", .{peekFirst}); - var peekLast = deque.last.?.data; // 队尾元素 - std.debug.print("\n队尾元素 peekLast = {}", .{peekLast}); + var peek_first = deque.first.?.data; // 队首元素 + std.debug.print("\n队首元素 peek_first = {}", .{peek_first}); + var peek_last = deque.last.?.data; // 队尾元素 + std.debug.print("\n队尾元素 peek_last = {}", .{peek_last}); // 元素出队 - var popFirst = deque.popFirst().?.data; // 队首元素出队 - std.debug.print("\n队首出队元素 popFirst = {},队首出队后 deque = ", .{popFirst}); + var pop_first = deque.popFirst().?.data; // 队首元素出队 + std.debug.print("\n队首出队元素 pop_first = {},队首出队后 deque = ", .{pop_first}); inc.PrintUtil.printQueue(i32, deque); - var popLast = deque.pop().?.data; // 队尾元素出队 - std.debug.print("\n队尾出队元素 popLast = {},队尾出队后 deque = ", .{popLast}); + var pop_last = deque.pop().?.data; // 队尾元素出队 + std.debug.print("\n队尾出队元素 pop_last = {},队尾出队后 deque = ", .{pop_last}); inc.PrintUtil.printQueue(i32, deque); // 获取双向队列的长度