开发者

Merge sort function (natural merge sort)

There are a few ways to do a merge sort, but I specifically need it to work like a natural merge sort. What happens in this algorithm is that smaller lists of numbers are generated in the file like so:

Original List: 35 27 24 28 31 37 1 4 7 6 8 9

Smaller List sections: [35], [27], [24, 28], [31, 37], [1, 4, 7], [6, 8, 9]

As you notice, everytime the unsorted list comes across a number that's smaller than it's present value, a new unit is created. Once the list ends, this list breaks into two other lists like so in an alternative fashion:

First list: [35], [24, 28], [1, 4, 7]

Second list: [27], [31, 37], [6, 8, 9]

The last step involves pulling the two lists together again, and the values are compared between the units in the first list item and the second list item as it traverses. For example, first unit in list one is compared with the first unit in list two and keeps the numbers in order. Any leftover units will be added on the end(Not shown).

Merging two lists: [27, 35], [24, 28, 31, 37], [1, 4, 6, 7, 8, 9]

This process will repeat until the list is sorted in one unit.

I have everything set up in this algorithm to work except for mer开发者_开发技巧ging the two lists and it's extremely hard to debug or locate the problem. It gets about halfway through before it goes into a segmentation fault. Anyways, I can't use the mergesort STL on this program and it's all in a linked list.

Note: The constructors and other necessary functions are already in place. I left out the other functions on purpose to empathize the specific function.

class mergeList
{
   public:

      //Setters
      void setNumber(int item);
      void setStart(bool newStatus);
      void setEnd(bool newStatus);
      void setPrev(mergeList* node);
      void setNext(mergeList* node);

      //Getters
      int getNumber();
      bool getStart();
      bool getEnd();
      mergeList* getPrev();
      mergeList* getNext();

   private:
      int number;

      bool startSection;
      bool endSection;

      mergeList* prev;
      mergeList* next;
};

class mergeListObject
{
   public:
     mergeList* firstNode;
     mergeList* lastNode;

   void mergeLists(mergeListObject &firstList,
                   mergeListObject &secondList);

   //Other functions in program are in here.
};

void mergeListObject::mergeLists(mergeListObject &firstList,
                                 mergeListObject &secondList)
{
   mergeList* combTraverse = firstNode;
   mergeList* firstTraverse = firstList.firstNode;
   mergeList* secondTraverse = secondList.firstNode;

   bool listDone = false;

   //This will clear the combination list for insertion
   while (combTraverse != NULL)
   {
      combTraverse->setNumber(-1);
      combTraverse->setStart(false);
      combTraverse->setEnd(false);

      combTraverse = combTraverse->getNext();
   }

   combTraverse = firstNode;

   combTraverse->setStart(true);

   while (listDone == false)
   {
      //This will go until the first list is traversed.
      do
      {
         bool exception = false;

         int j = firstTraverse->getNumber();
         int k;

         //If the second list is still active, this will
         //grab its current value for comparison.
         if (secondTraverse != NULL)
            k = secondTraverse->getNumber();

         //Second list is done, will automatically grab
         //first list's value and traverse through to the end.
         if (secondTraverse == NULL)
            combTraverse->setNumber(firstTraverse->getNumber());

         else
         {
            //Both values from both lists are compared.
            if (j <= k)
               combTraverse->setNumber(firstTraverse->getNumber());

            else
            {
                exception = true;
                combTraverse->setNumber(secondTraverse->getNumber());
            }
         }

         //If the first value unit was used, move the first list iterator up.
         //Otherwise, the second list's iterator moves up.
         if (exception == false)
            firstTraverse = firstTraverse->getNext();

         else
            secondTraverse = secondTraverse->getNext();

         exception = false;
      }
      while (firstTraverse->getEnd() == false);

      //If the second list isn't done, this will finish it.
      do
      {
         combTraverse->setNumber(secondTraverse->getNumber());

         secondTraverse = secondTraverse->getNext();
         combTraverse = combTraverse->getNext();
      }
      while (secondTraverse->getEnd() == false);

      combTraverse->setEnd(true);

      //Marks the end of the section and sets the next one,
      //considering it isn't the end of the list.
      if (combTraverse->getNext() != NULL)
         combTraverse->getNext()->setStart(true);

      //Both of these should end up at the start of a unit in their own lists.
      firstTraverse = firstTraverse->getNext();
      secondTraverse = secondTraverse->getNext();

      //Are both lists done?
      if (firstTraverse == NULL &&
          secondTraverse == NULL)
         listDone = true;
   }

   return;
}

int main()
{
   mergeListObject one;
   mergeListObject two;
   mergeListObject combined;

   //The two lists are already separated. All
   //other functions have already been called.

   combined.mergeLists(one, two);

   return 0;
} 


The first bug I could spot was at the end of your merge function :

firstTraverse = firstTraverse->getNext();
secondTraverse = secondTraverse->getNext();

may generate runtime error ("access violation" or "segmentation fault" depending on compiler and OS) you have to change it to

if (firstTraverse)
    firstTraverse = firstTraverse->getNext();
if (secondTraverse)
    secondTraverse = secondTraverse->getNext();

note that those pointers can really be NULL.

you also have to change while (firstTraverse->getEnd() == false); to while(firstTraverse & firstTraverse->getEnd() == false); again firstTravers can be NULL as long as first list has lower number of partitions than second list.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜