簡體   English   中英

C - 交換單鏈表中的第一個和最后一個元素

[英]C - Swap first and last element in singly linked list

我想做的是交換單鏈表的第一個和最后一個元素。 到目前為止,我有以下代碼,我在其中創建了一個列表並向其中添加了一些數字。 我的問題出在 swapElements1 function。

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

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

void addNodeSingle(struct node **head, int num, int thesi) //Function to insert new node at the beginning or the end of the list, depending on the value of "thesi"
{
    if (*head == NULL)
    {
        struct node *current;
        current = (struct node*) malloc (1*sizeof(struct node));
        current -> number = num;
        current -> next = NULL;
        *head = current;
    }

    else
    {
        if (thesi == 0)
        {
            struct node *current;
            current = (struct node*) malloc (1*sizeof(struct node));
            current -> number = num;
            current -> next = *head;
            *head = current;
        }

        else
        {
            struct node *current, *temp;
            current = (struct node*) malloc (1*sizeof(struct node));
            current -> number = num;
            temp = *head;
            while (temp -> next != NULL)
                temp = temp -> next;

            temp -> next = current;
            current -> next = NULL;
        }
    }
}

void displayList(struct node **head) //Function to display the list
{
    struct node *current;
    if(*head == NULL)
        printf("I lista einai adeia!\n");

    else
    {
    current= *head ;
        while(current != NULL)
        {
            printf("%d ",current -> number);
            current = current -> next;
        }
    }
}

void swapElements1(struct node **head) //(not working)Function to swap first and last element of the list
{
    struct node *current, *temp;
    current = temp = *head;

    while(current != NULL)
    {
        temp = current;
        current = current -> next;
    }

    *head = (*head)->next;
    *head = temp;
    current = NULL;
}

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

    addNodeSingle(&head,5,1);
    addNodeSingle(&head,6,1);
    addNodeSingle(&head,2,0);
    addNodeSingle(&head,7,0);
    addNodeSingle(&head,8,0);

    printf("List is: ");
    displayList(&head);
    swapElements1(&head);
    printf("\nNew list is: ");
    displayList(&head);
}

我得到的 output 是:

列表是:8 7 2 5 6

新名單是:6

我需要的是:

列表是:8 7 2 5 6

新列表是:6 7 2 5 8

這是一個演示

這顯然是錯誤的:

*head = (*head)->next;
*head = temp;

這只是用temp的值覆蓋了先前的值。 第一個陳述甚至可能不存在。

你從根本上需要兩次交換(技術上一次加上一次分配和終止)

  • 指向兩個節點的指針
  • 兩個節點的next指針

后者的這些在技術上並不需要,需要直接分配,而新的尾部都需要有它的next設置為NULL終止新的列表。

下面顯示了一個完整的示例,對其進行了大量評論,希望能夠揭示正在發生的事情的算法。

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

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

void swapFirstAndLast(struct node **head)
{
    // don't bother unless we have a list of at least two nodes
    if (!*head || !(*head)->next)
        return;

    // start with the head's next pointer (the second node in the list)
    struct node **pp = &(*head)->next;

    // walk the pointer-to-pointer down the list, each time grasping
    //  the next node's "next" pointer address until we reach a node
    //  whose 'next' is NULL. When that happens, `pp` will hold the
    //  address of the pointer pointing to the last node in the list
    while (*pp && (*pp)->next)
        pp = &(*pp)->next;

    // swap the pointer held in *head with *pp
    struct node *tmp = *head;
    *head = *pp;
    *pp = tmp;

    // save new head's next pointer to be the old head's next
    (*head)->next = (*pp)->next;

    // and finally, terminate the list.
    (*pp)->next = NULL;
}

void print_list(const struct node *head)
{
    while (head)
    {
        printf("%d ", head->data);
        head = head->next;
    }
    fputc('\n', stdout);
}

int main()
{
    struct node *head = NULL, **pp = &head;
    for (int i=1; i<=5; ++i)
    {
        *pp = malloc(sizeof **pp);
        (*pp)->data = i;
        pp = &(*pp)->next;
    }
    *pp = NULL;

    print_list(head);

    swapFirstAndLast(&head);

    print_list(head);
}

輸出

1 2 3 4 5 
5 2 3 4 1 

我已經為您留下了清單清理工作(毫無疑問,您已經編寫了這樣的算法)。 這其中的關鍵是如何使用指向指針的指針來操作鏈表的指針; 不僅僅是一堆臨時指針。 我強烈建議您在調試器中單步執行交換功能,觀察每一步發生的情況。

WhozCraig 的回答已經很完美了,但也許您可能希望通過一些調整來查看自己的代碼。 基本上,我所做的是在一次迭代之前停止對最后一個元素的搜索,這樣 temp 將停在 5,當前停在 6。此外,您必須使用指針進行四次更改,就像 WhozCraig 所做的那樣。 這是您的代碼,稍作修改:

void swapElements1(struct node **head) //(not working)Function to swap first and last element of the list
{
    struct node *current, *temp;
    current = temp = *head;

    while(current->next != NULL)
    {
        temp = current;
        current = current -> next;
    }
    temp->next = *head;
    current->next = (*head)->next;
    (*head)->next = NULL;
    *head = current;
}

這在我的機器上有效。 我將您的 while 循環條件從 current 更改為 current->next 並進行了正確的“指針更改”。 這些指針變化很難解釋,通常我會先寫在紙上,然后再寫在代碼中。

已經有人回答正確了,如果你們中的任何人在處理雙指針時遇到困難,請參考下面的答案。

void swap(){
if (!head || !(head -> next)){
    return;
}
node* tail = head;
while(tail -> next -> next != NULL){
    tail = tail -> next;
}
node* tmp = head;
head = tail -> next;
tail -> next = tmp;
head -> next = tmp -> next;
tmp -> next = NULL;
return;
}

我已將頭指針聲明為全局變量(這就是為什么我不需要在函數內部使用雙指針)。

下面是我的結構定義供大家參考

typedef struct node{
int data;
struct node *next;
}node;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM