可以通过更改引用来对链表进行排序吗?

时间:2017-03-25 12:09:47

标签: c sorting linked-list bubble-sort

我尝试使用冒泡排序算法对链接列表进行排序,方法是更改​​节点的引用。我搜索过很多书和互联网,但我发现排序方法可以改变节点之间信息部分的值。 我想要做的是通过改变列表的行进顺序进行排序,而不是它们之间的值。 这是我的代码。 PS:排序算法不起作用。 它不是合并排序列表的重复,因为它完全是另一种算法。

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define LINESIZE 128
struct Student {
    float medie;
    char nrMatricol[10];
    char *nume;
    char facltate[6];
};
struct Nod{
    Student stud;
    Nod* next;
};
Nod* inserareNodEnd(Nod *l,Student st)
{
    Nod *nou = (Nod*)malloc(sizeof(Nod));
    nou->next = NULL;//NOU->NEXT=0
    nou->stud = st;
    if (!l) {
        //lista este goala
        return nou;
    }
    else
    {
     //lista contine un nod
        Nod *t = l;
        while (t->next) {
            t = t->next;
        }
        t->next = nou;
        return l;
    }

}
float medieStudenti(Nod *lista) {
    float suma=0;
    int i=0;
    Nod *aux=lista;
    while (aux->next) {
        aux = aux->next;
        suma += aux->stud.medie;
        i++;
    }
    return suma/i;
}
Nod *stergerePrimulNodLista(Nod *l,Student *st) {
    if (l) {
        Nod *aux = l;
        l = l->next;
        aux->next = NULL;
        *st = aux->stud;
        //aux->next = NULL;
        free(aux);

    }
        return l;
}
Nod* sortareLista(Nod *l) {
    Nod *i=l;
    Nod *j=l;
    Nod *aux=l;
    Nod *min=l;
    min = i;
    while (i->next) {

        if (i->stud.medie < min->stud.medie) {
            min = i;
        }
        i = i->next;

    }
    i = l;
    int n = 0;
    while (i->next) {
        j = i->next;
        while (j->next) {
            if (i->stud.medie > j->stud.medie) {
                aux = i->next;
                i->next = j->next;
                j->next = aux;
            }
            j = j->next;
        }
        i = i->next;
    }

    return min;
    //return l;
}
void dezalocare(Nod *lista) {
    Nod *aux;
    aux = lista;
    while (aux->next) {
        lista = aux->next;
        free(aux->stud.nume);
        free(aux);
        aux = lista;
    }
}
void main()
{
    FILE *f;
    Student s;
    Nod *list=NULL;
    f = fopen("fisier.txt", "r");
    char fileBuff[LINESIZE], SEPARATORI[] = { "," };
    char *token;
    while (fgets(fileBuff, LINESIZE, f)) {
        token = strtok(fileBuff, SEPARATORI);
        strcpy(s.nrMatricol, token);
        //extragere token nume student din aceeasi linie
        //salvata in file Buff
        token = strtok(NULL, SEPARATORI);
        s.nume = (char*)malloc(sizeof(char)*strlen(token) + 1);
        strcpy(s.nume, token);
        token = strtok(NULL, SEPARATORI);
        strcpy(s.facltate, token);
        //extragere tokeni medie si conversia tokenului la float
        token = strtok(NULL, SEPARATORI);
        s.medie = atof(token);
        list = inserareNodEnd(list, s);
        printf("%s %s \n", s.nrMatricol, s.nume);
    }
    Nod *tmp = list;
    while (tmp) {
        printf("\nSe afiseaza din lista");
        printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
        tmp = tmp->next;
    }

    fclose(f);
    //determinarea mediei pentru studentii din lista
    float media = medieStudenti(list);
    printf("\nMedia este %.2f", media);
    //sortare lista dupa medie(cu modificarea adreselor de legatura)

    //tema dezalocare lista
    //tema dezalocari la nivel de aplicatie
    printf("\nAcesta este Ionel %s %s \n", s.nrMatricol, s.nume);
//  list = stergerePrimulNodLista(list, &s);
    tmp = list;
    while (tmp) {
        printf("\nSe afiseaza din lista");
        printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
        tmp = tmp->next;
    }

     tmp = list;
    while (tmp) {
        printf("\nSe afiseaza  lista sortata");
        printf("%s %s \n", tmp->stud.nrMatricol, tmp->stud.nume);
        tmp = tmp->next;
    }
    dezalocare(list);
  }

2 个答案:

答案 0 :(得分:0)

根据原始海报的要求,链表的冒泡排序示例。

更新 - 已删除<span class="error-message" ng-show="form1.phone.$dirty &&form1.phone.$invalid"></span> <div id="characters"> <span>Characters left: {{maxLength - message.description.length}}</span> ,而是使用pnEnd(ptr到未排序列表的结尾)。

swap

答案 1 :(得分:0)

首先:bubblesort很糟糕。 对于链表,它更可怕...... [&#34;自然&#34;对链表进行排序的方法是merge-sort,因为拉链合并两个已排序的链表很容易]

对于冒泡排序,基本操作是:

  • {比较两个相邻节点,并且MAYBE交换它们}
  • 并重复此操作,直到没有任何变化。
  • 这意味着最后的传球总是什么都没做。
#include <stdio.h>

struct node{
        struct node *next;
        int value;
        };

struct node nodes[] =
{{ nodes+1, 9}
,{ nodes+2, 5}
,{ nodes+3, 0}
,{ nodes+4, 1}
,{ nodes+5, 4}
,{ nodes+6, 7}
,{ nodes+7, 2}
,{ nodes+8, 3}
,{ nodes+9, 8}
,{ NULL   , 6}
        };

void node_printlist(struct node *p) {
for (   ;p; p=p->next) {
        printf("%d\n", p->value);
        }
}

unsigned node_bubblepass(struct node **pp)
{
struct node *one, *two;
unsigned swaps;

for (swaps=0 ; one = *pp; pp=&(*pp)->next) {
        two = one->next;
        if(!two) break;
        if(two->value >= one->value) continue;
                /* wrong order: swap them*/
        one->next = two->next;
        two->next = one;
        *pp = two;
        swaps++;
        }
return swaps;
}

void node_bubblesort(struct node **pp)
{
unsigned swaps;
do      {
        swaps = node_bubblepass(pp);
        } while (swaps);
}

int main(void){
struct node *root =nodes;

printf("Original:\n");
node_printlist(root);

node_bubblesort(&root);

printf("Result:\n");
node_printlist(root);

return 0;
}

在内圈中更新(感谢@rcgldr),当我们点击之前已经被冒泡的物品时,我们可以停止向下冒泡。

struct node * node_bubblepass_2(struct node **pp, struct node *end)
{
struct node *one, *two;

for ( ; one = *pp; pp=&(*pp)->next) {
        two = one->next;
        if(two == end) break;
        if(two->value >= one->value) continue;
                /* wrong order: swap them*/
        one->next = two->next;
        two->next = one;
        *pp = two;
        }
return one;
}

void node_bubblesort_2(struct node **pp)
{
 struct node *end = NULL;
do      {
        end = node_bubblepass_2(pp, end);
        } while (*pp != end);
}