Top 14 # Xem Nhiều Nhất Cấu Trúc Be Set To / 2023 Mới Nhất 12/2022 # Top Like | Comforttinhdauthom.com

Cấu Trúc Dữ Liệu Disjoint Sets / 2023

Bài 1: Ma trận kề C++/Pascal Lý thuyết đồ thị

Bài 2: Danh sách cạnh C++ Lý thuyết đồ thị

Bài 3: Danh sách kề C++ Lý thuyết đồ thị

Bài 4: Thuật toán tìm kiếm theo chiều sâu DFS pascal c++

Bài 5: Thuật toán tìm kiếm theo chiều rộng BFS pascal c++

Bài 6: Thuật toán loang trên ma trận

Cấu trúc dữ liệu Disjoint Sets

Nguồn đề bài: http://www.spoj.com/KSTN/problems/DS2509/

1. Đề bài Cấu trúc dữ liệu Disjoint Sets

Disjoint-set hiểu 1 cách đơn giản là 1 cách lưu trữ các tập hợp phần tử của 1 tập lớn cho trước.

Các phép toán thường được quan tâm tới trong disjoint-set là:

MakeSet(i): tạo ra 1 tập chỉ có i.

FindSet(i): tìm tập hợp mà nút i thuộc.

Union(i,j): ghép 2 tập hợp chứa i và j với nhau.

Xét bài toán:

Cho 1 đồ thị gồm N đỉnh được đánh số từ 1 đến N, giữa 2 đỉnh bất kỳ đều có thể nối hoặc không nối với nhau. Ở trạng thái ban đầu tất cả các đỉnh đều không có cạnh nối.

Bạn được cho một số yêu cầu, trong đó mỗi yêu cầu có 2 dạng:

Union(x, y): X Y 1 có ý nghĩa là bạn cần nối 2 đỉnh X và Y.

Find(x, y): X Y 2 có ý nghĩa là bạn cần cho biết với trạng thái như hiện tại thì 2 đỉnh X và Y có thuộc cùng một thành phần liên thông hay không? Hai đỉnh được coi là thuộc cùng một thành phần liên thông nếu có đường đi từ đỉnh này đến đỉnh kia qua 1 số đỉnh khác và 2 đỉnh liên tiếp trên đường đi đều có cạnh nối.

Dòng đầu tiên ghi một số nguyên dương P là số yêu cầu.

Trong P dòng tiếp theo, mỗi dòng ghi ba số nguyên dương X, Y, Z với ý nghĩa có yêu cầu loại Z với 2 đỉnh X và Y.

Với mỗi yêu cầu dạng X Y 2 (với Z = 2) bạn cần ghi ra số 0 hoặc 1 trên 1 dòng tùy thuộc 2 đỉnh X và Y không thuộc hoặc thuộc cùng một thành phần liên thông.

2. Code Disjoint Sets (Pascal và C++):

a. Code pascal

Cấu trúc dữ liệu Disjoint Sets, cau truc du lieu disjoint sets

Disjoint Set Cấu Trúc Dữ Liệu Đơn Giản Mà Hiệu Quả / 2023

Bất kì bài toán tin học nào cũng được giải quyết dựa trên thuật toán (Algorithm) và cấu trúc dữ liệu biểu diễn nó (Data Structure). Algorithms + Data Structures = Programs Tuy nhiên, trong quá trình giải quết bài toán ta thường quá chú tâm tới giải thuật mà quên mất rằng việc lựa chọn cấu trúc dữ liệu hợp lý ảnh hưởng rất nhiều tới thuật toán. Hay hiệu quả của thuật toán phụ thuộc vào cấu trúc dữ liệu được sử dụng.

Cấu trúc dữ liệu cũng rất đa dạng từ những cấu trúc dữ liệu đơn giản như mảng một chiều, nhiều chiều tới ngăn xếp, hàng đợi, bảng băm, cấu trúc dữ liệu dạng cây như cây nhị phân, heap, … và những cấu trúc dữ liệu nâng cao khác.

Ngoài ra còn có một dạng cấu trúc dữ liệu cài đặt khá đơn giản nhưng rất hiệu quả trong nhiều bài toán đó là Disjoint set.

Disjoint set là gì ?

Theo wikipedia: https://en.wikipedia.org/wiki/Disjoint-set_data_structure

Disjoint set là một cấu trúc dữ liệu theo dõi (tracking) một tập các phần tử được phân chia thành các tập con khác nhau không chồng chéo nhau (non-overlapping). Hay đơn giản hơn ta có ví dụ sau:Bài toán 1 Ta có 6 thành phố là A, B, C, D, E, F. Thành phố A có thể đi tới thành phố B và C. Thành phố B có thể đi tới thành phố D. Thành phố E có thể đi tới thành phố F. Các thành phố xảy ra chiến tranh những thành phố có đường đi trưc tiếp ( chẳng hạn từ A tới B và C) hoặc gián tiếp ( từ A tới D qua B) thì tướng lĩnh của thành phố đó có thể đem quân đánh chiếm thành phố khác sáp nhập làm của mình tạo thành một vùng mới và có 1 vị vua cai quản. Vậy khi tàn cuộc có bao nhiêu vùng đất khác nhau được cai quản bởi các vị vua. Để tìm số vùng đất được cai quản bởi các vị vua khác nhau ta sẽ chia tập hợp các thành phố {A, B, C, D, E, F} thành các tập con sao cho hai tập con bất kì không thể có đường đi từ thành phố của tập con này tới thành phố của tập con kia. Dễ thấy các vùng đất {A, B, C, D} có đường đi với nhau cuối cùng sẽ gộp chung lại thành 1 vùng đất được cai quản bởi 1 vị vua. Tuy nhiên vị vua đó không thể tiến đánh các thành phố E, F do không có đường đi. Cuối cùng sẽ chỉ có 2 vùng đất được tạo thành bởi các thành phố {A, B, C, D} và {E, F}.

Bài toán 2 Với một bài toán tương tự nhưng ta xét một ví dụ dễ biểu diễn trong máy tính hơn đó là: Cho tập hợp gồm N phần tử A = {1, 2, 3, 4, 5, 6, 7, 8 } các phần tử (1, 2) (1, 3) (2, 3) (4, 7) (4, 8) (5, 6) có liên kết với nhau. Tìm các tập hợp con mà giữa 2 tập hợp không có liên kết trực tiếp hoặc gián tiếp.

Nếu không sử dụng ý tưởng cấu trúc dữ liệu disjoint set ta có cách tiếp cận sau Sử dụng mảng link[] để theo dõi liên kết giữa 2 phần tử tức phần tử 1 và 8 có liên kết với nhau nếu link[1] = link[8]. Giả sử ban đầu chưa có liên kết nào được thêm vào thì mỗi phần tử sẽ là 1 tập con link[] = {1, 2, 3, 4, 5, 6, 7, 8}. Bây giờ ta sẽ duyệt qua tất cả phần tử và kiểm tra liên kết trực tiếp của nó. Khi thêm liên kết ta sẽ thực hiện 2 thao tác đó là

find(x, y) kiểm tra x và y có liên kết chưa (link[x] == link[y])

union(x, y) hợp x vào y và tất cả các phần tử liên kết với x cũng đều liên kết với y.

Chẳng hạn: Bắt đầu với 1 có

Tiếp theo với phần tử 2

Ý tưởng của disjoint set

Lúc này ta có 3 cây với 3 root là 5, 6, 4 là 3 tập hợp con. Do ta xây dựng 3 tập hợp con là cấu trúc dạng cây nên để kiểm tra 2 phần tử có liên kết hay không ta chỉ cần kiểm tra xem chúng có chung root hay không find(x, y) sẽ thực hiện findSet(x) == findSet(y) với findSet(x) trả về phần tử root của tập hợp chứa x. Ví dụ findSet(2) = 4, findSet(7) = 4. Độ phức tạp thuật toán là O(logN) hàm findSet sẽ đệ quy theo chiều cao của cây.

Cài đặt disjoint set

Ở bước khởi tạo ta coi mỗi phần tử là 1 cây với 1 nút root là chính nó thông qua makeSet(x)

Tiếp theo ta viết hàm xác định tập hợp (cây) chứa x

Cuối cùng là union thay vì luôn gắn root của cây chứa y vào root của cây chứa x ta thực hiện union by rank

Với các ví dụ trên việc áp dụng cấu trúc dữ liệu disjoint set thay vì độ phức tạp là O(N2) sẽ có độ phức tạp là 0(NlogN)

Ứng dụng

Ta cần xây dựng 1 hệ thống cáp nối tất cả các điểm trong thành phố A, B, C, D, … Tuy nhiên chi phí cáp giữa các điểm là khác nhau. MST giúp ta xác định đươc 1 hệ thống (dạng cây) nối tất cả các điểm với chi phí nhỏ nhất như hình vẽ.

Ý tưởng của thuật toán Kruskal dựa trên disjoint set và tham lam đã được trình bày ở đây: https://viblo.asia/p/cac-dang-bai-su-dung-thuat-toan-tham-lam-greedy-algorithm-problems-924lJARYZPM#_cac-bai-toan-lien-quan-toi-do-thi-6

Xây dựng hệ thống đếm số lượng bạn chung (mutual friends)

Hiện tại một nhóm sinh viên trong trường đang có trang social networking giúp kết nối bạn bè trong trường học tương tác với nhau, những người e ngại việc sử dụng facebook do bị leak thông tin. Một trong số những tính năng mà adminstrator đang cần bạn phát triển đó là hiển thị số lượng bạn chung (mutual friend) của giữa X và Y ở đây tất những người bạn trực tiếp với X hay gián tiếp qua một người bạn Z của X lúc này có thể coi là bạn chung với Y. Các requirement bạn nhận được như sau:

Nếu user A gửi request cho user B thì A sẽ following B. A và B chỉ là bạn bè khi B cũng following A

Khi A và B đã là bạn bè, có thể xem được số lượng bạn chung giữa A và B.

Phân tích Đối với yêu cầu 1 ta xây dựng 1 mảng vector following[] cho từng user quản lí id của các user khác đang following A. Chẳng hạn following[3] sẽ là 1 vector chứa các id của user đang following user có id là 3. A và B là bạn bè khi following của B chứa id của A và ngược lại.

Khi A và B đã là bạn bè ta sẽ hợp (union) X và Y.

Đối với yêu cầu 2 khi nhận được yêu cầu đếm số lượng bạn chung giữa A và B ta chỉ việc kiểm tra xem A và B có chung root hay không nó có trả về số lượng thành viên của root đó.

Note: Ở trên ta cài đặt union by rank theo độ cao của cây. Tuy nhiên đối với bài toán này ta cần lưu trữ số lượng thành viên của root (số lượng phần tử trong cây của root) nên ta thực hiện union by size thay vì union by rank

Để dễ biểu diễn nhất ta quy định yêu cầu 1 sẽ truyền và params là ‘following’ A_id B_id với A_id là user_id người gửi request following cho B_id. yêu cầu 2 sẽ truyền params là ‘mutual friends’ A_id B_id.

Ta có implement đơn giản trong C như sau

Cấu Trúc Pretend, Cấu Trúc Intend, Cấu Trúc Guess / 2023

∠ ĐỌC THÊM Cấu trúc regret, cấu trúc remember, cấu trúc forget

∠ ĐỌC THÊM Cấu trúc, cách dùng Đảo ngữ trong tiếng Anh

Pretend trong tiếng Việt mang nghĩa là giả vờ, giải bộ.

1.1 Pretend to do something

Cấu trúc này được sử dụng để diễn tả việc chủ thể đã giả vờ, giả bộ hay ngụy tạo một hành động, một việc nào đó có mục đích và muốn người khác tin rằng điều đó là sự thật.

1.2 Những cấu trúc pretend thường gặp

Những cấu trúc pretend này được sử dụng để tuyên bố, đòi hỏi, giả vờ hay làm một việc gì đó.

Khoá học TOEIC trực tuyến của ELIGHT ONLINE được xây dựng dựa trên lộ trình dành cho người mất gốc. Bạn có thể học mọi lúc mọi nơi hơn 200 bài học, cung cấp kiến thức toàn diện, dễ dàng tiếp thu với phương pháp Gamification.

Khoá học trực tuyến dành cho:

☀ Các bạn mất gốc Tiếng Anh hoặc mới bắt đầu học Tiếng Anh nhưng chưa có lộ trình ôn thi TOEIC phù hợp

☀ Các bạn có quỹ thời gian eo hẹp nhưng vẫn mong muốn thi lấy chứng chỉ TOEIC với điểm cao

☀ Các bạn muốn tiết kiệm chi phí ôn thi TOEIC nhưng vẫn đạt hiệu quả cao

Intend trong tiếng Việt mang nghĩa là dự định, có ý muốn, có ý định.

2.1 Intend to do something

Cấu trúc intend này được sử dụng khi chủ thể có dự định, ý định làm gì đó và những ý định này được lên sẵn kế hoạch hay hướng đến một mục đích nào đó.

Chú ý: Intend doing something

Cấu trúc intend này cũng được dùng để diễn tả việc có ý định, dự định làm gì đó.

2.2 Một số cấu trúc Intend khác thường gặp.

Cấu trúc intend này được sử dụng để diễn tả việc sự định, dự kiến của ai đó sẽ nhận hoặc chịu tác động của cái gì.

Cấu trúc intend này được dùng khi chủ thể dự kiến về một cái gì đó sẽ ra sao hoặc như thế nào.

Cấu trúc intend này được sử dụng khi chủ thể dự kiến cái gì sẽ có ý nghĩa nào đó.

Guess trong tiếng Việt mang nghĩa là dự đoán, phỏng đoán, đoán.

Cấu trúc guess được sử dụng khi chủ thể cố gắng đưa ra nhận định hay câu trả lời về một nhận định nào đó nhưng không chắc chắn.

Cấu trúc guess được dùng khi chủ thể muốn tìm ra câu trả lời đúng cho một câu hỏi hay một sự thật nào đó mà chủ thể chưa biết chắc.

Ví dụ: You would never guess (that) he had problems. He is always so cheerful.

(bạn sẽ không bao giờ đoán được anh ấy có vấn đề. Anh ấy luôn vui vẻ.)

Where do you… going for your holidays this year?

I can … the results.

What do you … to do now?

He didn’t … to kill his idea.

He … pretended an interest he did not feel.

You will never … who I saw yesterday!

Sách Tiếng Anh Cơ Bản là bộ học liệu độc quyền do Elight xây dựng, cung cấp đầy đủ kiến thức nền tảng tiếng Anh bao gồm Phát Âm, Từ Vựng, Ngữ Pháp và lộ trình ôn luyện bài bản 4 kỹ năng Nghe, Nói, Đọc Viết.

Bộ sách này dành cho:

☀ Học viên cần học vững chắc nền tảng tiếng Anh, phù hợp với mọi lứa tuổi.

☀ Học sinh, sinh viên cần tài liệu, lộ trình tỉ mỉ để ôn thi cuối kỳ, các kì thi quốc gia, TOEIC, B1…

☀ Học viên cần khắc phục điểm yếu về nghe nói, từ vựng, phản xạ giao tiếp Tiếng Anh.

Tìm Hiểu Map Và Set Trong Javascript / 2023

@kcjpop đăng ngày 25/03/2018

1255 từ – Đọc trong 4 phút

Hà Nội — minh họa bởi Jing Zhang

Được giới thiệu từ ES6, Map, Set, WeakMap, và WeakSet là những cấu trúc dữ liệu giúp thao tác trên tập hợp. Bài viết này sẽ giới thiệu cách hoạt động cũng như các ứng dụng của chúng.

Map

Map, mảng kết hợp (associate arrays) hay từ điển (dictionary/dict) là những thuật ngữ dùng để chỉ một cấu trúc dữ liệu, cho phép bạn ánh xạ từ một khóa (key) tương ứng với một giá trị (value). Trong JavaScript, chúng ta có thể sử dụng object để thể hiện cấu trúc này.

const dict = { hello: 'Xin chào', bye: 'Tạm biệt', } console.log(dict['hello'])

Tuy nhiên, nếu dùng object thì bạn chỉ có thể dùng chuỗi làm khóa. Ngoài ra, cách này cũng có một số hạn chế khác. Lớp Map do ES6 giới thiệu sẽ giúp giải quyết những vấn đề này. Với Map, bạn có thể sử dụng bất cứ dạng dữ liệu nào để làm khóa.

const obj = { bar: 2 } const dict = new Map() dict .set('foo', 123) .set(obj, 'hello world') dict.get('foo')

Bạn cũng có thể truyền vào hàm dựng của Map một mảng các cặp giá trị dạng [key, value], ví dụ như sau:

const dict = new Map([ ['foo', 123], [obj, 'hello world'] ])

Như đã nói ở trên, bạn có thể dùng bất cứ dạng dữ liệu gì để làm khóa cho Map, kể cả mảng, object, hàm, hay NaN.

Bản thân Map sử dụng phương thức so sánh SameValueZero để tìm khóa và giá trị tương ứng. SameValueZero hoạt động tương tự như ===, nhưng xem các giá trị NaN bằng nhau, cũng như +0 bằng -0.

Đố-hẻm-vui: Đố bạn kết quả của các biểu thức sau là gì?

Do SameValueZero nên hai object khác nhau sẽ là hai khóa riêng biệt.

const o1 = {} const o2 = {} dict.set(o1, 'Ô Một').set(o2, 'Ô Hai') dict.get(o2)

Nếu trong map đã có sẵn khóa, dữ liệu mới sẽ bị ghi đè lên.

const m = new Map() m.set('foo', 1) m.set('foo', 2) m.get('foo')

Để duyệt qua các khóa và giá trị trong Map, bạn có thể dùng:

const dict = new Map([ ['foo', 1], ['bar', 2] ]) dict.keys()

Bạn cũng có thể dùng toán tử spread ... với Map

const dict = new Map([ ['foo', 1], ['bar', 2] ]) console.log([ ['wut', 3], chúng tôi ])

Một số thao tác khác với Map.

const dict = new Map([ ['foo', 1], ['bar', 2] ])

Tại sao lại là size mà không phải length? Một số độc giả tinh ý sẽ nhận ra chúng ta dùng size thay vì length để đếm số cặp giá trị trong map. Lý do là vì: length dùng cho những chuỗi có thể index (đánh số) được, ví dụ với mảng ta có thể arr[3]. Ngược lại, size dành cho những cấu trúc không có thứ tự như Map và Set.

Set

Set là tập hợp các giá trị không bị trùng lặp, nghĩa là trong một set không thể có hai giá trị bằng nhau.

const s = new Set() set .add('red') .add('blue') .add('sweet') .add('you') chúng tôi

Bạn cũng có thể truyền một mảng vào hàm dựng của Set.

const s = new Set(['red', 'blue', 'sweet', 'red', 'you']) console.log(s)

Bạn cũng có thể thấy giá trị 'red' bị trùng lặp đã được loại bỏ. Chúng ta có thể áp dụng Set để tạo ra một mảng chứa những phần tử duy nhất.

const a = ['red', 'blue', 'sweet', 'red', 'you'] const b = [...new Set(a)] console.log(b)

Cũng tương tự như Map, Set sử dụng SameZeroValue để so sánh các phần tử với nhau.

const obj = {} const s = new Set([NaN, {}, obj]) s.has(NaN)

Để duyệt qua các phần tử của Set, bạn có thể dùng các phương thức như với Map.

const s = new Set([1, 2, 3, 4, 5])

Một số thao tác khác trên Set.

const s = new Set([1, 2, 3, 4, 5])

WeakMap và WeakSet

ES6 cũng giới thiệu hai lớp WeakMap và WeakSet. So với Map, các khóa của WeakMap bắt buộc phải là object, và chúng sẽ bị giải phóng khỏi bộ nhớ (garbage-collecting -- "hốt rác") đầu tiên nếu không có tham chiếu nào.

WeakMap có các phương thức tương tự như Map, ngoại trừ việc bạn không thể duyệt qua WeakMap bằng .keys(), .values(), .entries() hay for..of. Bạn cũng không thể .clear(), vì lý do an toàn dữ liệu.

Một ứng dụng của WeakMap là dùng để chứa dữ liệu private mà không gây ra rò rỉ bộ nhớ.

const privates = new WeakMap() class User { constructor() { const data = { phoneNumber: 123 } privates.set(this, data) } getPhoneNumber() { const data = privates.get(this) return data.phoneNumber } } const u = new User() console.log(u)

Tương tự như WeakMap, WeakSet cũng chỉ có thể chứa object, và nếu một phần tử trong WeakSet không có tham chiếu tới, nó sẽ bị giải phóng khỏi bộ nhớ.

Kết luận

Với những cải tiến so với object thông thường, Map sẽ là công cụ hữu hiệu để lưu trữ dữ liệu dạng (khóa, giá trị). Trong khi đó, Set giúp bạn lưu trữ chuỗi dữ liệu mà không lo lắng về việc trùng lắp giá trị.

Tham khảo

[1] Axel Rauschmayer. ECMAScript 6: maps and sets. Truy cập ngày 25 tháng 03 năm 2018 từ http://2ality.com/2015/01/es6-maps-sets.html

[3] Steve Brownlee. WeakMap for JavaScript Private Data. Truy cập ngày 25 tháng 03 năm 2018 từ https://www.stevebrownlee.com/weakmap-javascript-private-data/