mergesort mit listen. verbesserungsvorschläge?



  • die meisten algorithmenbücher schweigen sich darüber aus wie man am besten mergesort mit verketten listen implementiert. also hab ich mich mal versucht und bin aber nicht so ganz zufrieden, da dass ganze doch recht lang geworden ist. hat jemand vorschläge unter beibehaltung der eigenschaften (nur O(log n) zusätzlicher speicher) das ganze kürzer oder vor allem eleganter zu schreiben.

    #include <stdio.h>
    #include <stdlib.h>
    
    struct NodeStruct {
    	int value;
    	struct NodeStruct *next;
    };
    
    typedef struct NodeStruct Node;
    
    struct ListStruct {
    	int length;
    	Node *head;
    	Node *tail;
    };
    
    typedef struct ListStruct List;
    
    void split(List *l, List *half1, List *half2)
    {
    	int i;
    	Node *iter;
    
    	iter = l->head;
    	for (i = 0; i < l->length / 2 - 1; ++i) {
    		iter = iter->next;
    	}
    	half1->head = l->head;
    	half1->tail = iter;
    	half1->length = l->length / 2;
    	half2->head = iter->next;
    	half2->tail = l->tail;
    	half2->length = l->length - half1->length;
    	half1->tail->next = NULL;
    }
    
    void merge(List *list1, List *list2, List *result)
    {
    	Node *iter1;
    	Node *iter2;
    
    	iter1 = list1->head;
    	iter2 = list2->head;
    
    	if (iter1->value <= iter2->value) {
    		result->head = iter1;
    		result->tail = iter1;
    		iter1 = iter1->next;
    	} else {
    		result->head = iter2;
    		result->tail = iter2;
    		iter2 = iter2->next;
    	}
    	while (iter1 && iter2) {
    		if (iter1->value <= iter2->value) {
    			result->tail->next = iter1;
    			result->tail = iter1;
    			iter1 = iter1->next;
    		} else {
    			result->tail->next = iter2;
    			result->tail = iter2;
    			iter2 = iter2->next;
    		}
    	}
    	if (iter1) {
    		result->tail->next = iter1;
    		result->tail = list1->tail;
    	} else if (iter2) {
    		result->tail->next = iter2;
    		result->tail = list2->tail;
    	}
    	result->length = list1->length + list2->length;
    }
    
    void mergesort(List *l)
    {
    	List half1;
    	List half2;
    
    	if (l->length <= 1)
    		return;
    
    	split(l, &half1, &half2);
    	mergesort(&half1);
    	mergesort(&half2);
    	merge(&half1, &half2, l);
    }
    

    gruß danke



  • achja vor allem regt mich auch, dass ich length wissen muss.


Anmelden zum Antworten