交换链接列表中的节点而不交换数据

时间:2017-12-11 21:44:16

标签: c sorting linked-list bubble-sort

如何在不复制数据的情况下使用指针? 我想写一个冒泡排序功能,但我遇到了困难,需要一些帮助,如何交换节点地址而不是值。 我有一个包含城市名称和温度的文件:

  • 拉斯维加斯,25岁
  • 纽约,33
  • 芝加哥,23
  • 休斯顿,39

我需要按温度对其进行排序,然后将其写入另一个文件。

更新: 好的,现在我想我理解了理论部分:

// p is my node
// p-prev -> p -> p-next -> p-next-next
prev->next = p->next;
p->next = p->next->next;
prev->next->next = p;

这是我需要做的,交换节点,但从语法上来说,我无法使它工作。

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

struct node {
    char name[128];
    int id;
    struct node *next;
}*head;

void readFile() {
    char fnamer[128] = "";
    printf("\nEnter the file name to read (delimiter: ,): \n");
    scanf("%s",&fnamer);
    FILE *inf = fopen(fnamer, "r");

    char buffer[1024];
    memset(buffer, 0, 1024);
    while(fgets(buffer, 1024, inf)){
        struct node *temp = malloc(sizeof(struct node));
        temp->next = NULL;

        if(sscanf(buffer, "%19[^,], %d", temp->name, &temp->id) != 2){
            free(temp);
            break;
        }

        if(!head){
            head = temp;
        } else{
            temp->next = head;
            head = temp;
        }
    }

    fclose(inf);
}

int main(void) {
    // Read a linked list from file
    readFile();

    //Bubble sort in linked list
    struct node *loop1 = head;
    while(loop1){
        struct node *loop2 = loop1->next;
        while(loop2){
            if(loop1->id > loop2->id){

                // Swap next pointers
                // This is not working
                struct node *temp = loop1->next;
                loop1->next = loop2->next;
                loop2->next  = temp;

            }
            loop2 = loop2->next;
        }
        loop1 = loop1->next;
    }

    // Print the sorted linked list to file:
    char foutname[100]="";
    printf("\nPlease Enter the file name to write the result: \n");
    scanf("%s",&foutname);

    FILE *outf;
    outf = fopen(foutname, "w+");

    loop1 = head;
    while(loop1){
        printf("%s %d\n", loop1->name, loop1->id);
        fprintf(outf, "%s %d\n", loop1->name, loop1->id);
        loop1 = loop1->next;
    }
    fclose(outf);
    return 0;
}

2 个答案:

答案 0 :(得分:2)

要在单链表中交换两个节点,您可以使用以下功能

void swap(struct node **current)
{
    struct node *tmp = (*current)->next->next;
    (*current)->next->next = *current;
    *current = (*current)->next;
    (*current)->next->next = tmp;
}

例如,要交换头节点和下一个节点,您可以调用函数

swap( &head );

另请参阅此参考文献Bubble sort in c linked list的答案,其中显示了如何为单链表编写冒泡排序算法。

答案 1 :(得分:1)

我们需要交换next链接,以便重新安排链接链。如果您交换node1node2,则链接链应更改如下:

//change the link chain from
node0 -> node1 -> node2 -> node3
//to
node0 -> node2 -> node1 -> node3

我们把它放在while循环中,当没有更多交换时循环中断。我们可以通过限制数字比较来改进这个功能。在每个循环之后,应该对最后一个元素进行排序。

要将它们放在一起,我们可以使用typedef关键字,这样我们就不必在任何地方重复struct

typedef struct node_t
{
    char name[20];
    int id;
    struct node_t *next;
} node;

void bubblesort(node **list)
{
    if(!(*list)) return;
    node *previous_node = NULL;
    node *sort_up_to = NULL;
    while(1)
    {
        previous_node = NULL;
        node *ptr = *list;
        node *last_change = NULL;
        while(ptr->next)
        {
            //the rest of the list is sorted?
            if(sort_up_to && ptr == sort_up_to) break;

            node *next = ptr->next;
            if(ptr->id > next->id)
            {
                if(previous_node == NULL)
                    *list = next;
                else
                    previous_node->next = next;
                ptr->next = next->next;
                next->next = ptr;
                last_change = next;
            }

            previous_node = ptr;
            ptr = next;
        }

        //list is all sorted?
        if(!last_change) break;

        sort_up_to = last_change;
    }
}

int main(void)
{
    node* head = NULL;

    FILE *fin = fopen("test.txt", "r");
    if(!fin)
        return 0;

    node temp;
    while(fscanf(fin, "%19[^,], %d\n", temp.name, &temp.id) == 2)
    {
        node *n = malloc(sizeof(node));
        n->next = NULL;
        strcpy(n->name, temp.name);
        n->id = temp.id;
        if(head)
            n->next = head;
        head = n;
    }
    fclose(fin);

    bubblesort(&head);

    for(node* n = head; n != NULL; n = n->next)
        printf("%s %d\n", n->name, n->id);

    return 0;
}