简体   繁体   中英

How can I write merge-sort function that takes LinkedList& as input in C++?

Here is a declaration of my LinkedList:

struct LinkedList {
LinkedListNode *head, *tail;
LinkedList() { head = tail = NULL; }
~LinkedList() {
    Clear();
} //end-~LinkedList

void Clear() {
    while (head) {
        LinkedListNode* p = head;
        head = head->next;
        delete p;
    } //end-while

    head = tail = NULL;
} //end-Clear

void Append(int key) {
    LinkedListNode* node = new LinkedListNode(key);
    if (tail == NULL) head = tail = node;
    else {
        tail->next = node;
        tail = node;
    } //end-else
} //end-Append
};

Here is function body that I need to implement as this format in C++:

void MergeSort(LinkedList& list){ //I need to make merge sort with LinkedList }

Here is code that testing my sort algorithms, but merge sort does not work (by the way I can't change test side).

#define N 1024*32
int A[N];  
typedef void (*SortingFunction)(LinkedList &);

float Test(SortingFunction F, char *msg){
  int B[] = {4, 2, 5, 7, 8, 1, 10, 9, 15, 34, 6, 17, 66, 55, 44, 33};

  LinkedList list;
  for (int i = 0; i < sizeof(B) / sizeof(int); i++) {
      list.Append(B[i]);
  } //end-for

  // Use the sorting algorithm
  F(list);

  printf("Using %s to sort %d numbers...\n", msg, 16);

  // Check the result
  LinkedListNode* p = list.head;
  int S[] = { 1, 2, 4, 5, 6, 7, 8, 9, 10, 15, 17, 33, 34, 44, 55, 66 };
  for (int i = 0; i < sizeof(S) / sizeof(int); i++) {
      if (S[i] != p->key) return 0;
      p = p->next;
  } // end-for

  list.Clear();
  srand((unsigned int)time(NULL));
  int i;
  int min = INT_MAX;
  int max = 0;
  for (i=0; i<100;i++){
      int number = rand();
      list.Append(number);

      if (number<min) min=number;
      else if (number>max) max=number;
  } //end-for

  printf("Using %s to sort %d numbers...", msg, N);
  time_t t1 = time(NULL);
  F(list);
  time_t t2 = time(NULL);
  printf("took %I64d seconds\n", t2-t1);

  // Check the result
  if (list.head->key!=min || list.tail->key!=max) return 0;

  LinkedListNode* q = list.head;
  p = q->next;
  while (p){
    if (q->key > p->key) return 0;
    q = p;
    p = p->next;
  } //end-for

  return 100;
} //end-Test

/****************************************************
 * Main function
 ****************************************************/
int main(){
  float grade = 0;
  printf("======================= TEST4 =======================\n");
  grade += Test(MergeSort, "MergeSort");
  return 0;
} //end-main

Here is code that I wrote for merge sorting but it's not working, I think problem is function prototype. All of example that I have seen from internet using node pointer as function parameter. But in mine I have to pass reference as LinkedList&. I try some of codes but I couldn't achieve to get result. Also, here is code that I try but didn't get result.

void MergeSort(LinkedList& list){
    LinkedListNode* myhead = list.head;
    mergeSorting(myhead);

} //end-MergeSort
void mergeSorting(LinkedListNode*& head) {
    if (head->next != NULL)             
    {
        LinkedListNode* head1;
        LinkedListNode* head2 = head;
        int len = getLength(head);
        for (int i = 0; i < len / 2; i++)
        {
            head1 = head2;
            head2 = head2->next;
        }
        head1->next = NULL; 
        head1 = head;
        mergeSorting(head1);
        mergeSorting(head2);
        head = merge(head1, head2);
    }
}
int getLength(LinkedListNode* head) {
    LinkedListNode* cur = head;
    int i = 0;
    for (; cur != NULL; cur = cur->next) {
        i++;
    }
    return i;
}
LinkedListNode* merge(LinkedListNode*& head1, LinkedListNode*& head2) {
    LinkedListNode* newHead;
    if (head1 == NULL) return head2;
    else if (head2 == NULL) return head1;
    if (head1->key < head2->key) {
        newHead = head1;
        newHead->next = merge(head1->next, head2);
    }
    else {
        newHead = head2;
        newHead->next = merge(head1, head2->next);
    }
    return newHead;
}

The code needs a slightly different approach. mergeSorting should take a pointer to node as an input parameter, and return a pointer to node. The last 3 lines should be something like:

        head1 = mergeSorting(head1);
        head2 = mergeSorting(head2);
        return merge(head1, head2);

Then for the calling code:

void MergeSort(LinkedList& list){
    list.head = mergeSorting(list.head);
}

Assuming you're allowed to do a web search for example algorithms, a bottom up merge sort for linked lists is faster, but it's not based on the logic used for a bottom up merge sort for arrays. If interested, the wiki article has example pseudo code:

https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists

You tend to use references in places where they create confusion.

MergeSort should just take a pointer to the first node of the list and return a pointer to the first node of the sorted list.

merge should just take 2 pointers to initial nodes of sorted lists and return a pointer to the first node of the merged sorted list.

Here is a modified version:

void MergeSort(LinkedList& list) {
    LinkedListNode *cur = list.head = mergeSorting(list.head);
    if (cur) {
        while (cur->next)
            cur = cur->next;
    }
    list.tail = cur;
}
LinkedListNode *mergeSorting(LinkedListNode *head) {
    if (head->next != NULL) {
        LinkedListNode *head1;
        LinkedListNode *head2;
        LinkedListNode *prev = head;
        LinkedListNode *cur = head;
        int half = getLength(head) / 2;
        for (int i = 0; i < half; i++) {
            prev = cur;
            cur = cur->next;
        }
        prev->next = NULL; 
        head1 = mergeSorting(head);
        head2 = mergeSorting(cur);
        head = merge(head1, head2);
    }
    return head;
}
int getLength(const LinkedListNode *head) {
    const LinkedListNode* cur = head;
    int i = 0;
    for (; cur != NULL; cur = cur->next) {
        i++;
    }
    return i;
}
LinkedListNode *merge(LinkedListNode *head1, LinkedListNode *head2) {
    LinkedListNode *newHead;
    if (head1 == NULL)
        return head2;
    if (head2 == NULL)
        return head1;
    if (head1->key <= head2->key) {
        newHead = head1;
        newHead->next = merge(head1->next, head2);
    } else {
        newHead = head2;
        newHead->next = merge(head1, head2->next);
    }
    return newHead;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM