如何反转我在C中创建的链接列表

时间:2016-09-29 15:06:56

标签: c data-structures

我创建了一个链表,却想不出如何反转它。我知道算法,但我认为我在创建列表时犯了一个错误。反向功能有什么变化才能起作用。 以下是代码:

typedef struct Node{
    int data;
    struct Node* next;
} node;
node* head;
int count;
void insertAtBegin(int value){
    if(head==NULL){
        head = (node*)malloc(sizeof(node));
        head->data = 0;
        head->next = NULL;
    }
    node* newNode = (node*)malloc(sizeof(node));
    newNode->data = value;
    newNode->next = head->next;
    head->next = newNode;
    count++;
}

void display(){
    node* temp = (node*)malloc(sizeof(node));
    temp = head;
    while(temp->next!=NULL){
        printf("%d\t",temp->next->data);
        temp = temp->next;
    }
    printf("\n");
}

void reverse(){
    node *p, *q, *r;

    p = q = r = head;
    p = p->next->next;
    q = q->next;
    r->next = NULL;
    q->next = r;

    while (p != NULL){
        r = q;
        q = p;
        p = p->next;
        q->next = r;
    }
    head = q;
}

void main(){
    insertAtBegin(5);
    insertAtBegin(6);
    display();
    reverse();
    display();
    printf("\nSize of linked list is %d",count);
}

1 个答案:

答案 0 :(得分:1)

假设您有以下列表:

head = n0
n0 -> ... -> A -> B -> C -> D -> E -> ... -> nN -> NULL

你要反向:

head = nN
nN -> ... -> E -> D -> C -> B -> A -> ... -> n0 -> NULL

现在,让我们考虑列表开头已经颠倒并且您正在处理节点C的情况。你当时的名单是:

head = B
B -> A -> ... -> n0-> NULL
tmpHead  = C
C -> D -> E ... -> nN -> NULL

其中tmpHead是一个临时变量,可让您不会丢失对C的引用(因为B.next现在指向A)您希望:

  1. BC联系起来B C
  2. 之后
  3. 设置为C,反向列表的新主管
  4. D保留在临时变量tmpHead中,以便您仍然可以访问它
  5. 然后反转成为:

    node * tmp   = tmpHead.next;  // 3. part 1
    tmpHead.next = head;          // 1.
    head         = tmpHead;       // 2.
    tmpHead      = tmp;           // 3. part 2
    

    停止条件非常明显:当您到达列表末尾时必须停止,因此,当tmpHeadNULL时。至于初始化,head指向反转部分,tmpHead指向非反转部分。因此tmpHead必须设置为headhead设置为NULL

    最后,您将获得以下函数,该函数将指向列表第一个节点的指针作为输入参数

    void reverse(node ** head)
    {
      node * tmpHead = (* head);
      (* head)       = NULL;
    
      while(tmpHead)
      {
        node * tmp    = tmpHead->next;
        tmpHead->next = (* head);
        (* head)      = tmpHead;
        tmpHead       = tmp;
      }
    }
    

    请注意,在列表开头插入新节点的方式存在“问题”:您始终保持“幻像”节点,数据设置为0并且您调用head }。因此,我定义的列表的第一个真实节点是head->next。这意味着你必须像这样调用reverse函数:reverse(& (head->next))或略微修改函数。

    另外,请注意,您不应该转换malloc的结果。 Do I cast the result of malloc?