Loại này đã làm tôi chán nản trong một thời gian vì vậy tôi phải đến xem nó đã được giải quyết chưa. Đây là ý tưởng của tôi. Từ đầu, không phải là một ứng dụng của bất kỳ thuật toán nào tôi biết. Đây sẽ là một thuật toán vũ phu khá đắt tiền, nhưng nó sẽ khá hiệu quả. Giả sử bạn đang xử lý tập dữ liệu nhỏ thực sự mà bạn đã mô tả (100 hàng 4 cột) và đang làm việc trên máy tính hiện đại với đủ ram.
Tổng quan : Chúng tôi sử dụng thuật toán đệ quy trên danh sách được sắp xếp để phân tán các bản ghi tương tự với khoảng cách maxiumum của chúng trong các bản ghi tương tự. Sau mỗi cuộc gọi, tất cả các bản ghi có cùng cha mẹ đều ở khoảng cách tối đa. Cuộc gọi hàng đầu bao gồm tất cả các hồ sơ. Vì vậy, nó unorts từ trong ra ngoài.
Cấu trúc dữ liệu :
newIndexes
là một array<integer>
. Chỉ mục của mảng là chỉ mục hiện có của hàng. Giá trị sẽ là chỉ mục mới, bắt đầu bằng -1
data
là một array<array<string>>
. Khóa là chỉ mục, mảng bên trong là biểu diễn chuỗi của các giá trị trong một hàng. Không cần phải là một chuỗi nếu bạn có một số cách để nhóm dữ liệu của bạn. Phần tử mảng đầu tiên là phần tử có trọng lượng lớn nhất.
Sắp xếp data
theo thứ tự trọng lượng. Sắp xếp nó trước theo cột có trọng số lớn nhất, trong đó theo cột có trọng số lớn thứ 2, v.v ... Kết quả là nghịch đảo với những gì bạn muốn. Chỉ số tuần tự.
Đây là đại số (trong mã psudo).
// siblingCount: On first call is the number of rows in the table,
// on recursive calls it is the number of elements with the same parent
// index: the index of current row in `data` - starts 0
// depth: The element index - starts 0
void unsort(int siblingCount, int index, int depth)
{
int count = 1;
string hash = concatColumns(index, depth + 1);
while ((index + count < data.count) && (hash == concatColumns(index + count, depth + 1)))
{
count++;
}
if (depth < columnCount)
unsort(count, index, depth);
else if (index < data.count)
unsort(count, index + count, 0);
int spacing = siblingCount / count;
for (int i = 0; i < count; i++)
{
var offset = 0;
while ((newIndexes[index + i + offset] > -1) & (index + i + offset + 1 < newIndexes.count))
offset++;
if (newIndexes[index + i + offset] > -1) throw new Exception("Shouldn't happen.");
newIndexes[index + i + offset] = index + spacing * i;
}
}
string concatColumns(int index, int count) // returns count columns concatinated
{
// 1,1 = "1"
// 1,2 = "1, blue"
// 1,3 = "1, blue, apple"
return "1, blue, apple";
}
Sau đó, áp dụng các chỉ số mới cho dữ liệu để được sắp xếp.
Suy nghĩ về cách tiếp cận: Không kiểm tra điều này, nhưng việc lưu trữ các Index mới và giải quyết xung đột có thể gặp vấn đề vì các chỉ mục đầu tiên được chỉ định dựa trên các cột ít quan trọng nhất, vì vậy nếu có nhiều xung đột thì các cột quan trọng hơn có thể co cụm. Có thể thử áp dụng bù là dương trước, sau đó âm. Hoặc có thể thực hiện sắp xếp chèn trong danh sách được liên kết thay vì mảng.