2016-06-11 2 views
-1

링크 된 목록을 사전 순으로 정렬하려고하지만 내 정렬 알고리즘처럼 보이지 않습니다. 내 목록을 어떻게 정렬합니까?알파벳 순서로 연결된 목록을 C로 정렬하는 방법

+0

정렬 된 목록에서 위치를 찾으려면 각 요소를 다른 모든 요소와 비교해야합니다. (예, O (n^2) 비교가 필요없는 더 나은 알고리즘이 있습니다.) 버블 정렬 또는 선택 정렬에 대해 읽어보십시오. – SilentMonk

+0

목록에서 포인터 배열을 만든 다음 배열에서'qsort'를 호출하고 정렬 순서로 목록을 다시 채우는 것이 더 쉽습니다 (작은 목록을 제외하고는 훨씬 빠르지 만) –

+0

모든 코드 가장 큰 이름을 목록의 마지막 노드로 옮깁니다. 노드는 순서가 잘못 검출되지 않을 때까지 프로세스를 반복하기 위해 외부 루프가 필요합니다. 엄밀히 말하면 이것은 목록을 정렬하는 것이 아니라 노드 (구조)를 정렬하는 것과는 대조적으로 목록의 노드에서 이름을 정렬하는 것입니다. 한 가지 대안은 빈 목록으로 시작한 다음 원래 목록에서 노드를 제거하고 원래 비어있는 목록에 순서대로 "삽입"하여 원래 목록이 비었을 때 정렬 된 목록을 얻는 것입니다. – rcgldr

답변

0

코드를 한 번 더보고 나서 @TenTen Peter의 원래 의도와 일치하도록 최적화했습니다. 외부 루프는 필요하지 않습니다. 정렬이 제대로 수행됩니다

#include <stdlib.h> 
#include <stdio.h> 
#include <dirent.h> 
#include <string.h> 

// definition of the structure (global scope) 
typedef struct s_file 
{ 
    char  *file_name; 
    struct  s_file *next; 
} t_file; 

int static counter = 0; 

void sort_alpha(t_file **begin_list) 
{ 
    t_file *list; 
    char *tmp; 
    list = *begin_list; 
    if (list) 
    { 
     while (list && list->next) 
     { 
      if (strcmp(list->file_name, list->next->file_name) > 0) 
      { 
       tmp = list->file_name; 
       list->file_name = list->next->file_name; 
       list->next->file_name = tmp; 
       counter = counter + 1; 
       printf("swap=%d\n",counter); 
      } 
     list = list->next; 
     } 
    } 
} 

int list_size(t_file **alst) 
{ 
    int size = 0; 
    t_file *conductor; // This will point to each node as it traverses the list 
    conductor = *alst;  
    if (conductor != 0) 
    { 
     size = 1; 
     while (conductor->next != 0) 
     { 
      conductor = conductor->next; 
      size = size + 1; 
     } 
    } 
    return size; 
} 

void list_add(t_file **alst, t_file *newElement) 
{ 
    printf("list_add->"); 
    if (newElement) 
    { 
     newElement->next = *alst; 
     *alst = newElement; 

     // Printing the added element 
     printf("list_add:newElement=%s\n",(*alst)->file_name); 

     // sorting: 
     sort_alpha(alst); 
    } 
    else 
    { 
     printf("NULL entry\n"); 
    } 
} 

t_file *newEntry(char *file_name) 
{ 
    t_file *file; 
    file = (t_file *) malloc(sizeof(t_file)); 
    printf("newEntry:file_name= %s\n",file_name); 
    if (file) 
    { 
     file->file_name = file_name; 
     file->next = NULL; 
    } 
    return (file); 
} 

// Untested 
void read_dir(char *dir_name, t_file **begin_list) 
{ 
    DIR *dir; 
    struct dirent *entry; 
    dir = opendir(dir_name); 
    if (!dir) 
    { 
     perror(dir_name); 
     return; 
    } 
    while ((entry = readdir(dir)) != NULL){ 
     list_add(begin_list, newEntry(entry->d_name)); 
    }  
    closedir(dir); 
} 

int main(int ac, char **av) 
{ 
    t_file *s,*iter,*e2,*e3,*e4,*e5,*e6,*e7; 
    int j=0; 

    printf("*Program Start*\n");   

    // Creating entries: 
    s = newEntry("dHea"); 
    e2 = newEntry("bbcx"); 
    e3 = newEntry("abcd"); 
    e4 = newEntry("cbcd"); 
    e5 = newEntry("cbad"); 
    e6 = newEntry("bbcd"); 
    e7 = newEntry("cbaa"); 

    // Adding entries to the list and sorting at the same time 
    list_add(&s, e2); 
    list_add(&s, e3); 
    list_add(&s, e4); 
    list_add(&s, e5); 
    list_add(&s, e6); 
    list_add(&s, e7); 

    // It was done by: 
    // read_dir(av[1], &s); // Untested 

    // Print the sorted list 
    iter = s; 
    while (iter) 
    { 
     j++; 
     printf("Printing sorted list: element %d = %s\n",j,iter->file_name); 
     iter = iter->next; 
    } 

    printf("*Program End**\n"); 
    return 0; 
} 

출력 :

*Program Start* 
newEntry:file_name= dHea 
newEntry:file_name= bbcx 
newEntry:file_name= abcd 
newEntry:file_name= cbcd 
newEntry:file_name= cbad 
newEntry:file_name= bbcd 
newEntry:file_name= cbaa 
list_add->list_add:newElement=bbcx 
list_add->list_add:newElement=abcd 
list_add->list_add:newElement=cbcd 
swap=1 
swap=2 
list_add->list_add:newElement=cbad 
swap=3 
swap=4 
list_add->list_add:newElement=bbcd 
swap=5 
list_add->list_add:newElement=cbaa 
swap=6 
swap=7 
swap=8 
Printing sorted list: element 1 = abcd 
Printing sorted list: element 2 = bbcd 
Printing sorted list: element 3 = bbcx 
Printing sorted list: element 4 = cbaa 
Printing sorted list: element 5 = cbad 
Printing sorted list: element 6 = cbcd 
Printing sorted list: element 7 = dHea 
*Program End** 

코드는 여기에 있습니다 : code

편집 : 하나 내가 스왑 카운터를 추가 한 위의 알고리즘의 효율성에 대한 우려가있을 수 있기 때문에. 그것은 포인터를 교환해야 할 필요가 몇 번 있었는지 계산합니다. (복사가 필요 없음). 위의 데이터의 알고리즘은 매우 효율적으로 보입니다. 우리의 7 가지 요소 목록에서 8 가지 스왑 만!

다양한 소팅 알고리즘이 분류되는 시간을 비교하는 :

버블 정렬 [기기 : O (N), 최악 : O (N^2)]

선택 정렬 [최고/최악 : O (N^2)]

삽입 정렬 [기기 : O (N), 최악 : O (N^2)]

퀵 [기기 : O (N LG N) 부근 : O (Ng N), 최악 : O (N^2)]

힙 정렬 (Heapsort) [최고/평균/최악 : O (N의 LG N)]

정렬 계산 [베스트/평균/최악 : O (N)]

기수 정렬 [베스트/평균/최악 : O (N)]

소스 위키 Sorting

우리가 동일한 데이터 세트에 대한 고전 거품 정렬 알고리즘하여 상기 알고리즘을 비교할 수 있습니다. 이 테스트 코드입니다 :

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

static int count = 0; 

int main(void) { 

    char name[10][8], tname[10][8], temp[8]; 
    int i, j, n; 

    printf("Enter the number of names\n"); 
    scanf("%d", &n); 
    printf("Enter %d names\n", n); 

    // reading names 
    for (i = 0; i < n; i++) 
    { 
     scanf("%s", name[i]); 
     strcpy(tname[i], name[i]); 
    } 

    // standard bubble sort 
    for (i = 0; i < n - 1 ; i++) 
    { 
     for (j = i + 1; j < n; j++) 
     { 
      if (strcmp(name[i], name[j]) > 0) 
      { 
       strcpy(temp, name[i]); 
       strcpy(name[i], name[j]); 
       strcpy(name[j], temp); 

       count = count + 1; 
       printf("swap %d ", count); 
      } 
     } 
    } 

    // Print results: 
    printf("\n----------------------------------------\n"); 
    printf("Input Names \tSorted names\n"); 
    printf("------------------------------------------\n"); 
    for (i = 0; i < n; i++) 
    { 
     printf("%s\t\t\t%s\n", tname[i], name[i]); 
    } 
    printf("------------------------------------------\n"); 
    return 0; 
} 

입력 :

7 dHea bbcx abcd cbcd cbad bbcd cbaa 

그 결과, 우리가 필요로 동일한 데이터 세트에 대한 그래서

Enter the number of names 
Enter 7 names 
swap 1 swap 2 swap 3 swap 4 swap 5 swap 6 swap 7 swap 8 swap 9 swap 10 swap 11 swap 12 swap 13 
---------------------------------------- 
Input Names  Sorted names 
------------------------------------------ 
dHea   abcd 
bbcx   bbcd 
abcd   bbcx 
cbcd   cbaa 
cbad   cbad 
bbcd   cbcd 
cbaa   dHea 

reference

13 sw aps는 버블 정렬 알고리즘에서 알파 알고리즘처럼 8 대신에 사용됩니다.

(이 특정 버블 정렬은 strcpy 함수 대 스와핑 포인터를 사용합니다.)

나의 결론은 "알파 정렬"알고리즘이 일 때 항상이 고전적인 버블 정렬보다 더 효율적이라는 것입니다. 이는 정렬 된 목록에 요소를 순차적으로 정렬하기 시작하기 때문입니다. 기본적으로이 알고리즘을 개선 된 버블 정렬로 처리 할 수 ​​있습니다.

증가하는 목록은 항상 정렬되므로 일부 유형의 응용 프로그램에 매우 유용 할 수 있습니다.

+0

왜 'list_add'에서 sort를 호출하는 경우 단순히 정렬 순서로 노드를 추가하지 않는 것이 왜 영상화하기가 어렵습니다. 새 노드 앞에 노드를 찾아서 삽입 할 때까지 (예를 들어'cbcd '삽입,'a, b, c, cb, cba, [insert here]'반복 할 때까지 반복을 반복하면됩니다.) 처음에 노드 삽입 그리고 나서 모든 삽입에 대해 전체 목록 정렬을 호출하면 목록 크기가 커질수록 더 비효율적이됩니다. 'list_add'에서 정렬하는 경우 정렬 순서로 노드를 삽입하는 것이 가장 좋습니다. –

+0

@ DavidC.Rankin "전체 sort ". 우리는 원소를 복사하는 것이 아니라 포인터를 바꿀뿐입니다. void list_add (t_file ** alst, t_file * newElement);와 void sort_alpha (t_file ** begin_list);에 대한 제안을 게시 할 수 있습니까? 효율성? 덜 비용이 드는 일을 할 수 있고 여전히 작동하는지 궁금합니다. – sg7

+0

글쎄, 코드가 무엇을하는지, 내 포인트는 모든 포인터를 정렬 순서 삽입 점까지 스왑한다는 것입니다. 단순히 삽입 지점에 삽입됩니다. 대안은'list_add'에서'sort_alpha'를 취하는 것입니다 complet 모든 데이터를 읽은 후에 한 번만 호출하십시오. 서면으로, 당신은 불필요하게 시작 노드로서 순서에 맞지 않은 노드를 삽입 한 다음 추가 된 모든 노드에 대해 * 추가 ​​된 노드에 맞는 모든 포인터를 바꿔 넣을 수 있습니다 *. 귀하의 코드가 작동하지 않는다고 말하는 것이 아닙니다. 단지 덜 효율적인 방법으로 코딩하는 것이 어려울 것이라고 말하는 것입니다. –

관련 문제