Điều đó là rất có thể. Tôi đã đưa ra một giải pháp có khả năng không tối ưu nhưng cho thấy rằng nó có thể được thực hiện. Đầu tiên chia nó thành hai vấn đề: đảo ngược các con trỏ tiếp theo và đảo ngược các con trỏ ngẫu nhiên.
Đảo ngược các con trỏ tiếp theo:
node* last = NULL;
node* current = head;
node* next = head->next;
while (current != NULL)
{
current->next = last;
last = current;
current = next;
if (current != NULL)
next = current->next;
}
head = last
Đảo ngược danh sách ngẫu nhiên là một chút phức tạp hơn, chỉ vì chúng ta không có một danh sách của tất cả những người đứng đầu của chuỗi con trỏ ngẫu nhiên, nhưng chúng ta có thể tìm ra tận cùng chúng (các nút sẽ là một con trỏ ngẫu nhiên NULL). Chúng tôi sẽ cần một số chức năng trợ giúp để làm điều đó. Đầu tiên là một để đảo ngược một danh sách ngẫu nhiên. Chúng tôi phần lớn sao chép mã từ phía trên. Lưu ý rằng chúng ta đang thiết lập kết thúc chuỗi là một giá trị đặc biệt. Điều này khiến chúng tôi không thể hoàn nguyên danh sách. Xem thảo luận trong phần bình luận để được giải thích.
node* chainTail = malloc(1); //mallocing here to get a unique pointer
void reverseRandom(node* rhead)
{
node* last = chainTail;
node* current = rhead;
node* next = rhead->random;
while (current != NULL)
{
current->random = last;
last = current;
current = next;
if (current != NULL)
next = current->random;
}
}
Chúng tôi cũng cần một hàm trợ giúp để tìm cha mẹ của nút (hoặc trả về NULL nếu không có). Chúng tôi sẽ thực hiện tìm kiếm tuyến tính câm:
node* findParent(node* target)
{
node* candidate = head;
while ((candidate != NULL) && (candidate->random != target))
candidate = candidate->next;
return candidate;
}
Bây giờ chúng ta chỉ cần đi bộ danh sách, tìm thấy bất kỳ nút mà có một giá trị ngẫu nhiên của NULL (đuôi chuỗi của chúng tôi), tìm người đứng đầu chuỗi của họ, và đảo ngược chuỗi:
node* current = head; //Current node in a linear walk looking for chain tails
while (current != NULL)
{
if (NULL == current->random)
{
//current is the tail of a random chain, lets find the head
node* curr = current; //Current node in the search for the chain hean
node* parent = findParent(curr);
while (parent != NULL)
{
curr = parent;
parent = findParent(curr);
}
//At this point, curr is the head of the random chain, so reverse it
reverseRandom(curr);
}
current = current->next;
}
//Clean up chainTail pointers
node* current;
for (current = head; current != NULL; current = current->next)
{
if (current->random == chainTail)
{
current->random = NULL;
}
}
free(chainTail); //Stop a memory leak if this is not a global
Tuyên bố từ chối trách nhiệm chuẩn: Tôi chưa chạy mã này. Nó có thể có lỗi. Tôi bắt đầu buồn ngủ gần cuối, vì vậy tôi có thể đã có một lỗi hợp lý, nhưng có vẻ như tôi làm việc.
Ngoài ra, nếu bạn đang tìm cách để đưa điều này vào sản xuất, thì không. Mã này chạy ở đâu đó xung quanh O (n^3). Điều này rất có thể không phải là giải pháp nhanh nhất. Nó sử dụng không gian liên tục (mặc dù thậm chí có thể được giảm bằng cách chia sẻ trong lớp lót và tích cực).
cảm ơn bạn đã trả lời. Nhưng, tôi chỉ có một vấn đề với nó .. Làm thế nào để bạn tránh tái đảo ngược một chuỗi ngẫu nhiên? Giả sử bạn đã đảo ngược một chuỗi ngẫu nhiên mà bạn đã bắt đầu ở đâu đó trong danh sách chính. Sau đó, khi bạn đi qua danh sách chính, bạn nhấn nút Node là thành viên của một chuỗi ngẫu nhiên trước đó bạn đã đảo ngược .. để làm điều đó, bạn cần thêm bookeeping .. làm thế nào để bạn theo dõi điều đó mà không cần thêm dung lượng lưu trữ? –
@arun_suresh Bạn đang ở trong đó có nguy cơ đảo ngược đôi, nhưng không phải là nơi bạn mong đợi nó. Việc đảo ngược con trỏ tiếp theo là tốt vì bạn chỉ đảo ngược các con trỏ tiếp theo trong hàm đầu tiên. Bạn đảo ngược các con trỏ ngẫu nhiên sau và để lại các con trỏ tiếp theo một mình, vì vậy không có nguy cơ ô nhiễm chéo. Hơn nữa, vì không có hai nút trỏ đến cùng một con trỏ ngẫu nhiên, điều đó cũng an toàn. Nguy cơ duy nhất là người đứng đầu của một chuỗi là tiếp tục trong danh sách hơn so với đuôi vì vậy chúng tôi đầu tiên đảo ngược nó khi chúng tôi nhấn đuôi và một lần nữa khi chúng tôi nhấn đuôi mới. –
Ok, vâng, giải pháp đơn giản: Có đuôi đuôi mới không phải với NULL nhưng với giá trị đặc biệt và sau đó làm sạch chúng sau khi chúng tôi hoàn tất việc đảo ngược. Tôi sẽ chỉnh sửa câu hỏi. –