Thread: merge sort over (doubly) linked lists

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    57

    merge sort over (doubly) linked lists

    I'm having some trouble with my merge sort routines.

    I tried to implement some pseudo-code I found on Wikipedia thats supposed to be optimized for tape drives(since tape drives have the same strengths as a list), but it doesn't seem to change the order at all.

    Because of this I have a feeling it will be very obvious but I cant see the problem for the life of me.

    Thanks

    Code:
    void mergeClauses(struct clause_t *left, struct clause_t *right, 
    		  struct clause_t **output) {
    	bool t1, t2;
    	struct clause_t *node;
    	struct clause_t *l = left;
    	struct clause_t *r = right;
    
    	do {
    		if(l->numConflicts >= r->numConflicts) {
    			node = l;
    			l = l->next;
    			addClause(output, removeClause(&left, node));
    		} else  {
    			node = r;
    			r = r->next;
    			addClause(output, removeClause(&right, node));
    		}
    
    		if(l->next != NULL)
    			t1 = (l->numConflicts) > (l->next->numConflicts); 
    		else
    			t1 = false;
    		if(r->next != NULL)
    			t2 = (r->numConflicts) > (r->next->numConflicts); 
    		else
    			t2 = false;
    	} while(t1 && t2);
    
    	if(t1 == true)
    		addClause(output, removeClause(&left, l));
    	if(t2 == true)
    		addClause(output, removeClause(&right, r));
    }
    
    void sortClauses(struct clause_t **clauses) {
    	struct clause_t *input = *clauses; 
    	struct clause_t *output = NULL;
    	struct clause_t *tapeC = NULL;
    	struct clause_t *tapeD = NULL;
    
    	while(input != NULL) {
    		while(input != NULL) {
    			mergeClauses(input, output, &tapeC);	
    			mergeClauses(input, output, &tapeD);	
    		}
    
    		while(tapeC != NULL || tapeD != NULL) {
    			mergeClauses(tapeC, tapeD, &output);
    			mergeClauses(tapeC, tapeD, &input);
    		}
    	}
    
    	*clauses = output;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    Create a simple test program around it, which tests merging the following cases

    - two empty lists
    - one empty list, and one with one node.
    - two lists, each with one node.
    - L1=(A,B), L2=(C,D)
    - L1=(A,D), L2=(B,C)

    If these work, then think of other simple permutations.
    If not, then debug the code with these simple cases. Single-step the code in the debugger.

    With really simple cases, you can imagine what the result should be along the way. When reality diverges from expectation, you've found the bug (note: it might be your expectation which is the bug).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    57
    I decided I didn't really like Wikipedia's idea so I attempted something more straightforward. It just seemed overkill.

    Still doesn't work unfortunately. The list never seems to change order.

    Code:
    void mergeClauses(struct clause_t *l, struct clause_t *r, 
    		  struct clause_t **output) {
    	while(l != NULL || r != NULL) {
    		if(l != NULL) {
    			if(r != NULL) {
    				if(l->numConflicts <= r->numConflicts)
    					addClause(output, popClause(&l));
    				else
    					addClause(output, popClause(&r));
    			} else {
    				addClause(output, popClause(&l));
    			}
    		} else {
    			if(r != NULL)
    				addClause(output, popClause(&r));
    		}
    	}
    }
    
    void sortClauses(struct clause_t **input) {
    	struct clause_t *c;
    	struct clause_t *left = NULL; 
    	struct clause_t *right = NULL;
    
    	/* Base cases */
    	if(*input == NULL)
    		return;
    	if((*input)->next == NULL)
    		return;
    	
    	/* Divide */
    	while(true) {
    		c = popClause(input);
    		if(c != NULL)
    			addClause(&left, c);
    		else
    			break;
    
    		c = popClause(input);
    		if(c != NULL)
    			addClause(&right, c);
    		else
    			break;
    	}
    
    	/* Recurse */
    	sortClauses(&left);
    	sortClauses(&right);
    	mergeClauses(left, right, input);
    }

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    Like I said, post it with a main() and a simple test case, then we might be more interested.

    "Here is a random function" without context just means we try to spot the obvious and then move on.

    We don't want to (for every person that might help) have to imagine and create a test case just to help you. It is error prone and vastly inefficient.

    If you do this, then all we have to do is copy/paste/compile and then start looking for a real issue.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by zxcv View Post
    I decided I didn't really like Wikipedia's idea so I attempted something more straightforward. It just seemed overkill.
    Hint: Cut and Paste code almost always leads to more problems than it solves.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You now have what looks to be the correct code for an odd-even merge sort.

    Show the code for addClause and popClause. If they are implemented right then this code can't not change the list ordering (unless it's already sorted by numConflicts).
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Doubly linked lists
    By mohanlon in forum C Programming
    Replies: 8
    Last Post: 12-08-2010, 01:01 AM
  2. threaded merge sort
    By AusTex in forum Linux Programming
    Replies: 4
    Last Post: 05-04-2005, 04:03 AM
  3. Linked List of Linked lists Revisited.
    By Qui in forum C++ Programming
    Replies: 11
    Last Post: 04-11-2004, 09:45 PM
  4. Map file formats and linked lists
    By Spitball in forum Game Programming
    Replies: 2
    Last Post: 03-04-2004, 11:32 PM
  5. Merge Sort using a linked list
    By EvenFlow in forum C Programming
    Replies: 0
    Last Post: 10-04-2001, 11:07 PM