Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Ruby code - chapter "Stack & Queue" #1230

Merged
merged 1 commit into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions codes/ruby/chapter_stack_and_queue/array_deque.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
=begin
File: array_deque.rb
Created Time: 2024-04-05
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
=end

### 基于环形数组实现的双向队列 ###
class ArrayDeque
### 获取双向队列的长度 ###
attr_reader :size

### 构造方法 ###
def initialize(capacity)
@nums = Array.new(capacity, 0)
@front = 0
@size = 0
end

### 获取双向队列的容量 ###
def capacity
@nums.length
end

### 判断双向队列是否为空 ###
def is_empty?
size.zero?
end

### 队首入队 ###
def push_first(num)
if size == capacity
puts '双向队列已满'
return
end

# 队首指针向左移动一位
# 通过取余操作实现 front 越过数组头部后回到尾部
@front = index(@front - 1)
# 将 num 添加至队首
@nums[@front] = num
@size += 1
end

### 队尾入队 ###
def push_last(num)
if size == capacity
puts '双向队列已满'
return
end

# 计算队尾指针,指向队尾索引 + 1
rear = index(@front + size)
# 将 num 添加至队尾
@nums[rear] = num
@size += 1
end

### 队首出队 ###
def pop_first
num = peek_first
# 队首指针向后移动一位
@front = index(@front + 1)
@size -= 1
num
end

### 队尾出队 ###
def pop_last
num = peek_last
@size -= 1
num
end

### 访问队首元素 ###
def peek_first
raise IndexError, '双向队列为空' if is_empty?

@nums[@front]
end

### 访问队尾元素 ###
def peek_last
raise IndexError, '双向队列为空' if is_empty?

# 计算尾元素索引
last = index(@front + size - 1)
@nums[last]
end

### 返回数组用于打印 ###
def to_array
# 仅转换有效长度范围内的列表元素
res = []
for i in 0...size
res << @nums[index(@front + i)]
end
res
end

private

### 计算环形数组索引 ###
def index(i)
# 通过取余操作实现数组首尾相连
# 当 i 越过数组尾部后,回到头部
# 当 i 越过数组头部后,回到尾部
(i + capacity) % capacity
end
end

### Driver Code ###

# 初始化双向队列
deque = ArrayDeque.new(10)
deque.push_last(3)
deque.push_last(2)
deque.push_last(5)
puts "双向队列 deque = #{deque.to_array}"

# 访问元素
peek_first = deque.peek_first
puts "队首元素 peek_first = #{peek_first}"
peek_last = deque.peek_last
puts "队尾元素 peek_last = #{peek_last}"

# 元素入队
deque.push_last(4)
puts "元素 4 队尾入队后 deque = #{deque.to_array}"
deque.push_first(1)
puts "元素 1 队尾入队后 deque = #{deque.to_array}"

# 元素出队
pop_last = deque.pop_last
puts "队尾出队元素 = #{pop_last},队尾出队后 deque = #{deque.to_array}"
pop_first = deque.pop_first
puts "队尾出队元素 = #{pop_first},队尾出队后 deque = #{deque.to_array}"

# 获取双向队列的长度
size = deque.size
puts "双向队列长度 size = #{size}"

# 判断双向队列是否为空
is_empty = deque.is_empty?
puts "双向队列是否为空 = #{is_empty}"
106 changes: 106 additions & 0 deletions codes/ruby/chapter_stack_and_queue/array_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
=begin
File: array_queue.rb
Created Time: 2024-04-05
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
=end

### 基于环形数组实现的队列 ###
class ArrayQueue
### 获取队列的长度 ###
attr_reader :size

### 构造方法 ###
def initialize(size)
@nums = Array.new(size, 0) # 用于存储队列元素的数组
@front = 0 # 队首指针,指向队首元素
@size = 0 # 队列长度
end

### 获取队列的容量 ###
def capacity
@nums.length
end

### 判断队列是否为空 ###
def is_empty?
size.zero?
end

### 入队 ###
def push(num)
raise IndexError, '队列已满' if size == capacity

# 计算队尾指针,指向队尾索引 + 1
# 通过取余操作实现 rear 越过数组尾部后回到头部
rear = (@front + size) % capacity
# 将 num 添加至队尾
@nums[rear] = num
@size += 1
end

### 出队 ###
def pop
num = peek
# 队首指针向后移动一位,若越过尾部,则返回到数组头部
@front = (@front + 1) % capacity
@size -= 1
num
end

### 访问队首元素 ###
def peek
raise IndexError, '队列为空' if is_empty?

@nums[@front]
end

### 返回列表用于打印 ###
def to_array
res = Array.new(size, 0)
j = @front

for i in 0...size
res[i] = @nums[j % capacity]
j += 1
end

res
end
end

### Driver Code ###

# 初始化队列
queue = ArrayQueue.new(10)

# 元素入队
queue.push(1)
queue.push(3)
queue.push(2)
queue.push(5)
queue.push(4)
puts "队列 queue = #{queue.to_array}"

# 访问队首元素
peek = queue.peek
puts "队首元素 peek = #{peek}"

# 元素出队
pop = queue.pop
puts "出队元素 pop = #{pop}"
puts "出队后 queue = #{queue.to_array}"

# 获取队列的长度
size = queue.size
puts "队列长度 size = #{size}"

# 判断队列是否为空
is_empty = queue.is_empty?
puts "队列是否为空 = #{is_empty}"

# 测试环形数组
for i in 0...10
queue.push(i)
queue.pop
puts "第 #{i} 轮入队 + 出队后 queue = #{queue.to_array}"
end
77 changes: 77 additions & 0 deletions codes/ruby/chapter_stack_and_queue/array_stack.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
=begin
File: array_stack.rb
Created Time: 2024-04-06
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
=end

### 基于数组实现的栈 ###
class ArrayStack
### 构造方法 ###
def initialize
@stack = []
end

### 获取栈的长度 ###
def size
@stack.length
end

### 判断栈是否为空 ###
def is_empty?
@stack.empty?
end

### 入栈 ###
def push(item)
@stack << item
end

### 出栈 ###
def pop
raise IndexError, '栈为空' if is_empty?

@stack.pop
end

### 访问栈顶元素 ###
def peek
raise IndexError, '栈为空' if is_empty?

@stack.last
end

### 返回列表用于打印 ###
def to_array
@stack
end
end

### Driver Code ###

# 初始化栈
stack = ArrayStack.new

# 元素入栈
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
puts "栈 stack = #{stack.to_array}"

# 访问栈顶元素
peek = stack.peek
puts "栈顶元素 peek = #{peek}"

# 元素出栈
pop = stack.pop
puts "出栈元素 pop = #{pop}"
puts "出栈后 stack = #{stack.to_array}"

# 获取栈的长度
size = stack.size
puts "栈的长度 size = #{size}"

# 判断是否为空
is_empty = stack.is_empty?
puts "栈是否为空 = #{is_empty}"
41 changes: 41 additions & 0 deletions codes/ruby/chapter_stack_and_queue/deque.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
=begin
File: deque.rb
Created Time: 2024-04-06
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
=end

### Driver Code ###

# 初始化双向队列
# Ruby 没有内直的双端队列,只能把 Array 当作双端队列来使用
deque = []

# 元素如队
deque << 2
deque << 5
deque << 4
# 请注意,由于是数组,Array#unshift 方法的时间复杂度为 O(n)
deque.unshift(3)
krahets marked this conversation as resolved.
Show resolved Hide resolved
deque.unshift(1)
puts "双向队列 deque = #{deque}"

# 访问元素
peek_first = deque.first
puts "队首元素 peek_first = #{peek_first}"
peek_last = deque.last
puts "队尾元素 peek_last = #{peek_last}"

# 元素出队
# 请注意,由于是数组, Array#shift 方法的时间复杂度为 O(n)
pop_front = deque.shift
puts "队首出队元素 pop_front = #{pop_front},队首出队后 deque = #{deque}"
pop_back = deque.pop
puts "队尾出队元素 pop_back = #{pop_back}, 队尾出队后 deque = #{deque}"

# 获取双向队列的长度
size = deque.length
puts "双向队列长度 size = #{size}"

# 判断双向队列是否为空
is_empty = size.zero?
puts "双向队列是否为空 = #{is_empty}"
Loading