/* Splits a list into two halves to be merged */ static struct list *list_merge_sort(struct list *left, unsigned int len, comparison_fn_t comparison_fn) { struct list *right = NULL; unsigned int left_len = len / 2; unsigned int right_len = len / 2 + len % 2; unsigned int i; if (!left) { return NULL; } if (len == 1) { return left; } right = left; /* Split into left and right lists */ for (i = 0; i < left_len; i++) { right = right->next; } right->prev->next = NULL; right->prev = NULL; /* Recurse */ left = list_merge_sort(left, left_len, comparison_fn); right = list_merge_sort(right, right_len, comparison_fn); return list_merge(left, right, comparison_fn); }
/* e.g. void list_merge(node** head){ left = *head; *head = NULL; ... continue in the same manner but don't return */ node* list_merge_sort(node* left){ /* one element by itself is sorted */ if(!left->next){ return left; } node *middle = left, *end = left; /* find a suitable middle node at which to split */ while(end){ end = end->next; middle = middle->next; if(end){ end = end->next; } } /* break the list up */ node *right; if(middle->next != end){ right = middle->next; middle->next = NULL; }else{ right = left->next; left->next = NULL; } /* call recursively on halves */ left = list_merge_sort(left); right = list_merge_sort(right); /* put back together in order */ /* the first element of the list will change we need to track what that is and return it */ node *head = NULL, *pos = NULL; while(left || right){ /* check if we can use from left */ node* use = NULL; if(!right || (left && left->data <= right->data)){ use = left; left = left->next; } /* else use right as next */ else{ use = right; right = right->next; } /* the head is the first node used */ if(!head){ pos = head = use; } /* set the next node in the new list to use and move position to that */ pos->next = use; pos = use; } return head; }
int main(int argc,char *argv[],char *env[]) { list_t *plist = NULL; plist = list_create(); // srand(getpid()); int i; for(i = 0;i < 300000;i++) { int *ptmp = malloc(sizeof(int)); *ptmp = rand(); list_push_head(plist,ptmp); } // list_traverse(plist, print); // putchar('\n'); // list_insert_sort(plist, cmp); list_merge_sort(plist, cmp); if(list_issort(plist, cmp) == SUCCESS) printf("issort.\n"); list_destroy(plist,free_data); return 0; }
char *test_merge_sort() { list_t *words = create_words(); // should work on a list that needs sorting list_t *res = list_merge_sort(words, (list_compare)strcmp); mu_assert(is_sorted(res), "Words are not sorted after merge sort."); list_t *res2 = list_merge_sort(res, (list_compare)strcmp); mu_assert(is_sorted(res2), "Should still be sorted after merge sort."); list_destroy(&res2); list_destroy(&res); list_destroy(&words); return NULL; }
List * list_merge_sort(List *list, int size, List_Compare_Cb compare) { List *right, *left, *result; int i; if (size <= 1) return list; // Split the list into two halves left = list; right = list; for (i = 0; i < size/2; i++) right = right->next; right->prev->next = NULL; right->prev = NULL; // Sort the halves separately left = list_merge_sort(left, size/2, compare); right = list_merge_sort(right, (size+1)/2, compare); // Merge the sorted halves return list_sorted_merge(left, right, compare); }
void sort1(CL_FORM *base) { if(CL_LISTP(ARG(0))) { list_merge_sort(ARG(0)); } else { COPY(ARG(0), ARG(3)); LOAD_FIXNUM(ARG(4), 0, ARG(4)); COPY(ARG(0), ARG(5)); Flength(ARG(5)); COPY(ARG(1), ARG(6)); COPY(ARG(2), ARG(7)); quick_sort(ARG(3)); COPY(ARG(3), ARG(0)); } }
struct list *list_sort(struct list *list, comparison_fn_t comparison_fn) { list = list_head(list); unsigned int len = list_len(list); return list_merge_sort(list, len, comparison_fn); }
List * list_sort(List *list, List_Compare_Cb compare) { return list_merge_sort(list, list_count(list), compare); }
int main(int argc, char** argv){ node* list = filetolist(argv[1]); list = list_merge_sort(list); list_print(list); }
int run_access (newts_nfref *ref) { List access_list; short changed = FALSE; short redraw = TRUE; int c; int first = 0; int entries; entries = get_access_list (ref, &access_list); while (1) { if (redraw) display_access (&access_list, first, entries); redraw = FALSE; mvprintw (LINES - 2, 0, _("Option: ")); refresh (); c = getch (); switch (c) { case '?': access_help (); /* Fall through. */ case 'r': /* Redraw the screen. */ case '\f': redraw = TRUE; break; case '!': redraw = TRUE; spawn_subshell (); break; case 's': move (LINES - 2, 0); clrtoeol (); printw (_("Sorting...")); refresh (); list_merge_sort (&access_list); redraw = TRUE; break; case 'Q': /* Quit without saving. */ case 'K': list_destroy (&access_list); return 0; case 'q': case 'k': if (changed) { list_merge_sort (&access_list); write_access_list (ref, &access_list); } list_destroy (&access_list); return 0; case '-': case KEY_UP: case KEY_PPAGE: first -= c == KEY_UP ? 1 : (LINES - 6) / 2 - 1; if (first < 0) first = 0; redraw = TRUE; break; case '+': case KEY_DOWN: case KEY_NPAGE: first += c == KEY_DOWN ? 1 : (LINES - 6) / 2 - 1; if (first >= entries - (LINES - 6) / 2) { first = entries - (LINES - 6) - 3; if (first < 0) first = 0; } redraw = TRUE; break; case 'i': /* Insert new entries. */ { char *persistent_error = NULL; short stop = FALSE; while (entries < NPERMS && !stop) { ListNode *node; struct access *access_entry; char *temp, *name, *prompt; int key, i; int y, x; enum newts_access_scopes scope; int scope_is_set = FALSE; int mode; short restart = FALSE; short advice_displayed = FALSE; if (traditional) mvprintw (LINES - 5, 39, _("Entry type: ")); else { clear (); display_access (&access_list, first, entries); if (persistent_error != NULL) { move (LINES - 3, 0); clrtoeol (); printw ("%s", persistent_error); persistent_error = NULL; } move (LINES - 2, 0); clrtoeol (); printw (_("Entry type: ")); } refresh (); if (!traditional) advice_displayed = FALSE; getyx (stdscr, y, x); while (scope_is_set == FALSE) { key = getch (); if (key == '\n' || key == '\r' || key == KEY_ENTER || key == 'q' || key == 'k') { if (traditional && (key == 'k' || key == 'q')) echochar (key); stop = TRUE; break; } switch (key) { case 'u': if (traditional) { echochar (key); move (y, x); } scope = SCOPE_USER; scope_is_set = TRUE; break; case 'g': if (traditional) { echochar (key); move (y, x); } scope = SCOPE_GROUP; scope_is_set = TRUE; break; case 's': if (traditional) { echochar (key); move (y, x); } scope = SCOPE_SYSTEM; scope_is_set = TRUE; break; case KEY_RESIZE: break; case EOF: clear (); display_access (&access_list, first, entries); if (traditional) { if (advice_displayed) mvprintw (LINES - 5, 54, "(u,g,s, q,k,<cr>)"); move (LINES - 5, 51); } else { if (advice_displayed) mvprintw (LINES - 3, 0, _("Please enter 'u', 'g', or 's'; or " "'q', 'k', or <RET> to exit.")); mvprintw (LINES - 2, 0, _("Entry type: ")); } refresh (); break; default: advice_displayed = TRUE; if (traditional) { mvprintw (LINES - 5, 54, "(u,g,s, q,k,<cr>)"); move (LINES - 5, 51); } else { move (LINES - 3, 0); clrtoeol (); printw (_("Please enter 'u', 'g', or 's'; or 'q', " "'k', or <RET> to exit.")); move (LINES - 2, 0); clrtoeol (); printw (_("Entry type: ")); } refresh (); break; } } if (stop) continue; if (traditional) { prompt = newts_nmalloc (strlen (_("Name: ")) + 40, sizeof (char)); strcpy (prompt, " "); strncat (prompt, _("Name: "), strlen (_("Name: ")) + 1); move (LINES - 4, 0); clrtoeol (); } else { move (LINES - 3, 0); clrtoeol (); prompt = newts_strdup (scope == SCOPE_SYSTEM ? _("System name: ") : scope == SCOPE_GROUP ? _("Group name: ") : _("User name: ")); move (LINES - 2, 0); clrtoeol (); } refresh (); temp = gl_getline (prompt); temp[strlen (temp) - 1] = '\0'; newts_free (prompt); if (strlen (temp) == 0) continue; name = newts_strdup (temp); gl_histadd (name); if (scope == SCOPE_USER) { if (strcasecmp (name, "other") != 0) { struct passwd *pw = getpwnam (name); if (pw == NULL) { if (traditional) { move (LINES - 3, 0); clrtoeol (); mvprintw (LINES - 3, 39, _("--No such user--")); } else persistent_error = _("No such user."); continue; } endpwent (); } } if (scope == SCOPE_GROUP) { if (strcasecmp (name, "other") != 0) { struct group *gp = getgrnam (name); if (gp == NULL) { if (traditional) { move (LINES - 3, 0); clrtoeol (); mvprintw (LINES - 3, 39, _("--No such group--")); } else persistent_error = _("No such group."); continue; } endgrent (); } } node = list_head (&access_list); for (i=0; i<entries; i++) { access_entry = (struct access *) list_data (node); if (access_scope (access_entry) == scope && strcmp (access_name (access_entry), name) == 0) { if (traditional) { move (LINES - 3, 0); clrtoeol (); mvprintw (LINES - 3, 39, _("%s entry exists"), name); } else persistent_error = scope == SCOPE_USER ? _("User already exists in " "permission table.") : (scope == SCOPE_GROUP ? _("Group already exists in " "permission table.") : _("System already exists in permission table.")); restart = TRUE; continue; } node = list_next (node); if (node == NULL) continue; } if (restart) continue; { struct access *new_access = access_alloc (); access_set_permissions (new_access, READ | WRITE | REPLY); access_set_scope (new_access, scope); access_set_name (new_access, name); get_mode (new_access, &access_list, first, entries); list_insert_sorted (&access_list, (void *) new_access); } newts_free (name); entries++; redraw = TRUE; changed = TRUE; clear (); display_access (&access_list, first, entries); } if (!traditional) redraw = TRUE; break; } case 'd': /* Delete existing entries. */ { ListNode *node, *prev; struct access *data; int key, number, i; move (LINES - 2, 0); clrtoeol (); if (traditional) printw ("%s", _("Delete entry #: ")); else printw ("%s", _("Delete entry number: ")); key = getch (); while (key != '\n' && key != '\r' && key != KEY_ENTER && (key < '1' || key > '9')) key = getch (); if (key == '\n' || key == '\r' || key == KEY_ENTER) { redraw = TRUE; break; } number = get_number (key, entries); if (number < 0) { redraw = TRUE; break; } if (number > entries || key < '0' || key > '9' || number == 0) { clear (); display_access (&access_list, first, entries); if (traditional) { move (LINES - 1, 0); clrtoeol (); printw ("%s", _("Bad entry")); } else { move (LINES - 3, 0); clrtoeol (); printw ("%s", _("Invalid entry.")); } break; } number--; /* Adjust to base zero. */ prev = NULL; node = list_head (&access_list); for (i=0; i<number; i++) { prev = node; node = list_next (prev); } data = (struct access *) list_data (node); if (data->scope == SCOPE_USER && strcmp (data->name, username) == 0) { clear (); display_access (&access_list, first, entries); if (traditional) { move (LINES - 1, 0); clrtoeol (); printw ("%s", _(" Can't Delete self")); } else { move (LINES - 3, 0); clrtoeol (); printw ("%s", _("Can't delete own entry.")); } break; } list_remove_next (&access_list, prev, NULL); entries--; changed = TRUE; redraw = TRUE; break; } case 'm': /* Modify existing entries. */ { ListNode *node; struct access *existing_entry; int key, number, i; move (LINES - 2, 0); clrtoeol (); if (traditional) printw ("%s", _("Modify entry #: ")); else printw ("%s", _("Modify entry number: ")); key = getch (); while (key != '\n' && key != '\r' && key != KEY_ENTER && (key < '1' || key > '9')) key = getch (); if (key == '\n' || key == '\r' || key == KEY_ENTER) { redraw = TRUE; break; } number = get_number (key, entries); if (number < 0) { redraw = TRUE; break; } if (number > entries || key < '0' || key > '9' || number == 0) { clear (); display_access (&access_list, first, entries); if (traditional) { move (LINES - 1, 0); clrtoeol (); printw ("%s", _("Bad entry")); } else { move (LINES - 3, 0); clrtoeol (); printw ("%s", _("Invalid entry.")); } break; } number--; /* Adjust to base zero. */ node = list_head (&access_list); for (i=0; i<number; i++) { node = list_next (node); } existing_entry = (struct access *) list_data (node); get_mode (existing_entry, &access_list, first, entries); changed = TRUE; redraw = TRUE; break; } case '\004': list_destroy (&access_list); return QUITNOSEQ; case 'z': list_destroy (&access_list); return QUITSEQ; default: beep (); break; } } return 0; }