📜  链表的其他排序

📅  最后修改于: 2021-04-26 08:44:18             🧑  作者: Mango

给定一个包含n个节点的链表。问题是要重新排列列表中的节点,以使第一节点中的数据为第一最小值,第二节点为第一最大值,第三节点为第二最小值,第四节点为第二最大值,依此类推。

例子:

Input : list: 4->1->3->5->2
Output : 1->5->2->4->3

Input : list: 10->9->8->7->6->5
Output : 5->10->6->9->7->8

方法:以下是步骤:

  1. 使用合并排序技术对链接列表进行排序。
  2. 将列表分为列表和列表。请参阅这篇文章的FrontBackProcedure。
  3. 现在,反转后退列表。请参阅这篇文章。
  4. 最后,以交替顺序合并第一列表和后列表的节点。
// C++ implementation of alternative sorting
// of the Linked list
#include 
  
using namespace std;
  
// node of a linked list
struct Node {
    int data;
    struct Node* next;
};
  
// function to get a new node
Node* getNode(int data)
{
    // allocate space for node
    Node* newNode = (Node*)malloc(sizeof(Node));
  
    // put in the data
    newNode->data = data;
    newNode->next = NULL;
  
    return newNode;
}
  
// Split the nodes of the given list into front and 
// back halves, and return the two lists using the 
// reference parameters. If the length is odd, the 
// extra node should go in the front list. Uses the 
// fast/slow pointer strategy.
void FrontBackSplit(Node* source,
                    Node** frontRef, Node** backRef)
{
    Node* fast;
    Node* slow;
    if (source == NULL || source->next == NULL) {
        // length < 2 cases
        *frontRef = source;
        *backRef = NULL;
    }
    else {
        slow = source;
        fast = source->next;
  
        // Advance 'fast' two nodes, and
        // advance 'slow' one node
        while (fast != NULL) {
            fast = fast->next;
            if (fast != NULL) {
                slow = slow->next;
                fast = fast->next;
            }
        }
  
        // 'slow' is before the midpoint in the list,
        // so split it in two at that point.
        *frontRef = source;
        *backRef = slow->next;
        slow->next = NULL;
    }
}
  
// function to merge two sorted lists in
// sorted order
Node* SortedMerge(Node* a, Node* b)
{
    Node* result = NULL;
  
    // Base cases
    if (a == NULL)
        return b;
    else if (b == NULL)
        return a;
  
    // Pick either a or b, and recur
    if (a->data <= b->data) {
        result = a;
        result->next = SortedMerge(a->next, b);
    }
    else {
        result = b;
        result->next = SortedMerge(a, b->next);
    }
  
    return result;
}
  
// sorts the linked list by changing
// next pointers (not data)
void MergeSort(Node** headRef)
{
    Node* head = *headRef;
    Node *a, *b;
  
    // Base case -- length 0 or 1
    if ((head == NULL) || (head->next == NULL))
        return;
  
    // Split head into 'a' and 'b' sublists
    FrontBackSplit(head, &a, &b);
  
    // Recursively sort the sublists
    MergeSort(&a);
    MergeSort(&b);
  
    // merge the two sorted lists together
    *headRef = SortedMerge(a, b);
}
  
// function to reverse the linked list
static void reverse(Node** head_ref)
{
    Node* prev = NULL;
    Node* current = *head_ref;
    Node* next;
  
    while (current != NULL) {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
  
    *head_ref = prev;
}
  
// function to alternately merge two lists
void alternateMerge(Node* head1, Node* head2)
{
    Node *p, *q;
    while (head1 != NULL && head2 != NULL) {
  
        // merging nodes alternately by
        // making the desired links
        p = head1->next;
        head1->next = head2;
        head1 = p;
        q = head2->next;
        head2->next = head1;
        head2 = q;
    }
}
  
// function for alternative sort of the
// linked list
Node* altSortForLinkedList(Node* head)
{
    // sort the linked list
    MergeSort(&head);
  
    Node *front, *back;
  
    // Split head into 'front' and 'back' sublists
    FrontBackSplit(head, &front, &back);
  
    // reversing the 'back' list
    reverse(&back);
  
    // merging the nodes of 'front' and 'back'
    // lists alternately
    alternateMerge(front, back);
  
    // required head of final list
    return front;
}
  
// Function to print nodes in
// a given linked list
void printList(Node* head)
{
    while (head != NULL) {
        cout << head->data << " ";
        head = head->next;
    }
}
  
// Driver program to test above
int main()
{
    // linked list: 10->9->8->7->6->5
    Node* head = getNode(10);
    head->next = getNode(9);
    head->next->next = getNode(8);
    head->next->next->next = getNode(7);
    head->next->next->next->next = getNode(6);
    head->next->next->next->next->next = getNode(5);
  
    cout << "Original list: ";
    printList(head);
  
    head = altSortForLinkedList(head);
  
    cout << "\nModified list: ";
    printList(head);
  
    return 0;
}

输出:

Original list: 10 9 8 7 6 5
Modified list: 5 10 6 9 7 8

时间复杂度:O(n * logn)。