Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Cấu Trúc Dữ Liệu Cần Thiết Cho Ruby Developer: Hướng Dẫn Thực Hành

Cấu Trúc Dữ Liệu Là Gì?

Cấu trúc dữ liệu là cách cụ thể tổ chức & truy cập data. Ví dụ: Array, Binary tree, Hash. Cấu trúc khác nhau xuất sắc task khác nhau. Ví dụ, hash tuyệt vời nếu lưu data kiểu dictionary (từ & định nghĩa), hoặc phone book (tên & số). Biết cấu trúc nào available, và đặc điểm từng cái, làm bạn dev Ruby tốt hơn. Đó là điều bạn học bài này!

Hiểu Về Array

Array là cấu trúc dữ liệu đầu tiên học khi bắt đầu programming. Array dùng contiguous chunk memory, object lưu liền nhau không gap. Khác lower-level language như C, Ruby lo việc manage memory, mở rộng max size & compact khi xóa phần tử. Uses: Base cho cấu trúc nâng cao, gather kết quả loop, collect item. Array ở khắp nơi, như method split & chars tách string thành array char. Ví dụ:

 out = []
10.times { |i| out << i }
out # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
Bảng sau cho thấy operation array behave như thế nào khi size tăng. Nếu không quen time complexity notation đọc bài này. Time complexity array:
Operation Complexity
push O(1)
pop O(1)
access O(1)
find O(n)
delete O(n)
Tại sao hữu ích? Cho biết performance characteristic array. Làm nhiều find trên array KHỦNG LỚN sẽ chậm... Nhưng biết index dùng, array nhanh nhờ O(1) access. Chọn cấu trúc dữ liệu theo tiêu chí: 1. Performance characteristic => Làm gì với data? Dataset to bao nhiêu? 2. Hình dạng & dạng data => Data loại gì? Có re-organize data fit cấu trúc tốt hơn không?

Cấu Trúc Dữ Liệu Hash

Có mapping country code & tên nước? Hoặc chỉ muốn đếm thứ. Đó chính là hash hữu ích! Hash là cấu trúc mỗi value có key & key là bất kỳ thứ gì, string, integer, symbol, v.v. Cách hoạt động? Hash convert key thành số (dùng method hash Ruby) & dùng số đó làm index. Nhưng không cần hiểu sâu để dùng hash Ruby. Uses: Đếm ký tự string, map từ->định nghĩa, tên->số điện thoại, tìm duplicate trong array. Ví dụ:

 "aaabcd"
  .each_char
  .with_object(Hash.new(0)) { |ch, hash| hash[ch] += 1 }
# {"a"=>3, "b"=>1, "c"=>1, "d"=>1} 
Time complexity:
Operation Complexity
store O(1)
access O(1)
delete O(1)
find (value) O(n)
Hash là cấu trúc hữu ích nhất về performance nhờ constant O(1) store, delete, access. Find trong hash nghĩa là tìm value cụ thể.

Stack (Ngăn Xếp)

Stack như chồng đĩa, đặt đĩa lên trên & chỉ lấy đĩa trên cùng. Hữu ích hơn nghe! Uses: Thay recursive method bằng loop thường, track việc còn lại, để gần nhất lên trên, reverse array. Ví dụ:

 stack = [1,2,3,4,5]
(1..stack.size).map { stack.pop } # [5, 4, 3, 2, 1] 
Dùng reverse thay thế. Chỉ ví dụ cho thấy đặc điểm stack. Time complexity:
Operation Complexity
push O(1)
pop O(1)
find ---
access ---
Chú ý stack (và queue) chỉ có 2 operation, insert & delete, hoặc push & pop. Có thể search trong stack nhưng rất hiếm.

Cách Dùng Binary Tree (Cây Nhị Phân)

Phần lớn Ruby dev nghe binary tree nhưng chưa dùng. Tại sao? Thứ nhất, không có built-in implementation. Thứ hai, binary tree không helpful everyday challenge, khác array/hash dùng LUÔN. Nhưng binary tree rất thú vị. Cấu Trúc Dữ Liệu Cần Thiết Cho Ruby Developer: Hướng Dẫn Thực Hành Thực tế nhiều biến thể, như Trie (phần sau), multiway tree như B-Tree (dùng DB) & Heap. Uses: Nén dữ liệu, routing table, abstract syntax trees (AST). Ví dụ:

 # https://github.com/jamesconant/bstree
require 'bstree'
root = Bstree::Node.new(5)
root.insert(2)
root.insert(7)
root.search(3) # nil 
Time complexity:
Operation Complexity
insert O(log n)
delete O(log n)
find O(log n)
access ---
Balanced binary tree: tất cả node có 2 con & leaf cùng level. Unbalanced -> performance degrade O(n). Self-balanced binary tree (Red-Black, AVL), mọi operation tốn thời gian tỷ lệ height tree. Không có access time vì access node phải find trước... Trường hợp đó O(log n) access. Giữ reference (biến) đến node cụ thể -> O(1) access.

Cấu Trúc Dữ Liệu Trie

Trie là cấu trúc dữ liệu tree-like chuyên biệt. Hữu ích làm việc từ, tìm nhanh từ bắt đầu bằng prefix, hoặc tìm full word. Uses: Game từ, spell checker, autocomplete suggestion. Ví dụ:

 # https://github.com/gonzedge/rambling-trie
require 'rambling-trie'
trie = Rambling::Trie.create('words.txt')
trie.include?('chocolate') # true
trie.include?('salmon') # true 
Time complexity:
Operation Complexity
add O(k)
include? O(k)
words O(k)
Bảng dùng k chỉ size input string, n size cấu trúc dữ liệu. Với từ apple, k = 5.

Tóm Tắt

Bạn đã học cấu trúc dữ liệu phổ biến, use case chính & đặc điểm, cách dùng trong Ruby. Cấu Trúc Dữ Liệu Cần Thiết Cho Ruby Developer: Hướng Dẫn Thực Hành Áp dụng kiến thức mới giải quyết vấn đề nhanh hơn! Có thể share bài nếu hữu ích? Cảm ơn 🙂