Hỏi về cách sử dụng bảng băm

Hi @DoNg,
Mình xin trả lời câu hỏi của bạn :

  • Về mặt kỹ thuật:

Cách dùng này là không được vì kiểu của khóa của map<kiểu khóa, kiểu giá trị> phải là kiểu dữ liệu so sánh được. Trong đó data là cấu trúc dữ liệu bạn tự định nghĩa, chưa có toán tử thứ tự.
Để giải quyết, bạn cần xây dựng toán tử thứ tự cho struct data:

typedef struct data
        {
        string name;
        int color;
        bool operator <(const data &Data) 
                {
                      return (this->name < Data.name);
                }
        }

Điều này có nghĩa là thứ tự được quyết định giữa 2 đối tượng kiểu data dựa vào thuộc tính name của nó, trong đó phép so sánh này giữa 2 kiểu dữ liệu string lại được quyết định nhờ operator khác được định nghĩa trong lớp string.
Ngoài ra, thuộc tính định thứ tự còn là thuộc tính quyết định sự duy nhất của khóa.
Ví dụ, nếu bạn so sánh dựa vào thuộc tính name thì có nghĩa là hai node A , B khác nhau sẽ được map < data, data > Graph; coi là khác nhau nếu A.name != B.name, còn các thuộc tính khác không có giá trị quyết định sự khác nhau, ngoài ra, nếu A.name == B.name thì A,B khi truyền vào map làm key thì được coi như là một.
Theo mình thì nên so sánh dựa trên địa chỉ của data được cấp phát:
return (this < &Data); // không chắc nữa :smiley:
Truy cập hay chèn phần tử vào map có thể dùng qua toán tử [];

  • Về mặt ý nghĩa:
    Nếu bạn dùng map < data, data > Graph; để lưu danh sách cạnh thì có thể bị mất thông tin vì data đầu tiên trong map là khóa, do đó nó được lưu DUY NHẤT, nếu gán nó lần 2 thì nó chồng lên lần đầu:
    VD:Lưu cạnh AB và AC:
    Graph[A]=B
    Graph[A]=C
    ==> Graph[A] cho kết quả là C, C đã ghi đè lên B.
    Kiểm tra Graph.size()=1 :’(
    Vì thế mình khuyên bạn gói 2 kiểu data sang 1 bên key:
    map<string,bool>, trong đó string là ghép của (A.name+B.name)
    S= (A.name+B.Name); map[S]=true; S= (A.name+C.Name); map[S]=true;
    Kiểm tra: Graph.size()=2 // (^_^)
    Nếu không mình khuyên bạn dùng pair<string,string> làm khóa.

Mình nói có sai các bạn góp ý giúp nha.
`

so sánh dựa trên địa chỉ của data được cấp phát:

ko đúng vì ví dụ 2 chuỗi “abc” và “abc” giống nhau nhưng có thể được cấp phát ở 2 địa chỉ khác nhau. Nếu so sánh dựa trên địa chỉ thì ko có chuỗi nào giống chuỗi nào cả.

có thể dùng map< data, vector<data> > hoặc map< data, list<data> > để lưu

nên dùng mảng để lưu danh sách cạnh. Cho trước V đỉnh, tạo mảng Chứa V list/vector, khỏi cần xài map

2 Likes

Hi, ý mình là địa chỉ của data, tức là cái struct á bạn, còn chuỗi thì chỉ là thuộc tính của struct.

Tự vì mình nghĩ là bạn ấy muốn truy xuất nhanh thông qua tên đỉnh (kiểu string) nên mình tận dụng cây tìm kiếm nhị phân của map. Nếu dùng vector thì là sao mình truy xuất bằng khóa kiểu bất kỳ được bạn?. Mình cũng không biết cách khác nữa ~~

đỉnh đồ thị thì đánh số hết cho tiện, nếu đỉnh đồ thị xài bằng string thì mất công tốn O(logV) mỗi lần tìm đỉnh X chẳng hạn. Đánh số, xài mảng thì truy cập ví dụ đỉnh thứ 3 thì chỉ cần O(1) lẹ hơn.

1 Like

Đúng là nếu đỉnh đánh số thì tốt quá rồi , nhưng mà theo yêu cầu thì tên đỉnh phải dùng bằng chữ cái , nên e muốn dùng map để tìm cho nhanh danh sách đỉnh kề chứ ko định duyệt thứ tự sẽ lâu (:

Đúng :slight_smile: hihi , vậy mình dùng map< data , set < data> > thì ko lo bị ghi đè nhỉ !

2 Likes

Khi làm theo cách này mình gặp 1 vấn đề là làm sao có thể thay đổi giá trị của Data , ví dụ thay đổi giá trị color, compile báo đó là biến const , mình đã xóa chữ const ở khai báo nhưng cũng ko ăn thua ! Vậy bạn có biết cách xử lý thế nào ko ạ !??

Mình cũng không rành nữa. Hay bạn thử lưu một map khác làm color á. Mình khỏi dùng struct, thuộc tính của đỉnh bây giờ chỉ là name thôi, do đó mình dùng chuỗi luôn á.
map<string,set<string>> Graph; map<string,int> Color;
Bạn thấy được không ? :smiley:

ukm , như vậy lúc tìm kiếm , so sánh, rồi tô màu đồ thị , mình phải duyệt 2 map riêng !! để thử tiếp vậy :)) tks bạn nhiều !

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?