链表逆置的两种方法——头插法和就地逆置

初学数据结构,链表的操作除了增、删、改、查功能外,链表还有一项比较重要的操作——链表的逆置。于是对其进行了一番简单的研究。

首先,我们来创建一个链表(含头结点)

#include                                                                                                                                        
#include

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

node *creat(int n){
     
    node *head,*p,*q;
    int num;
    head = (node*)malloc(sizeof(node));
    head->next = NULL;
    q = head;
    while(n--){
     
        scanf("%d",&num);
        p = (node*)malloc(sizeof(node));
        p->data = num;
        q->next = p;
        q = p;
    }
    q->next = NULL;
    return head;
}

之后,介绍我们的第一种逆置方法:头插法

所谓头插法,就是使用一个结构体指针向后遍历,用另一个指针将前一个结点插入到头结点指向的下一个位置

//头插
void reverse_head(node *head){
     
    node *p,*q;
    p = head->next; //使用 p 依次向后遍历
    head->next = NULL;
    while(p){
     
        //前一负责指向插入结点的指针后移
        //在第二次 while 循环时看这个操作更清楚
        q = p;
        //向后遍历
        p = p->next;    
        //将 q 结点插入到头结点后面                                                                                                                          
        q->next = head->next;
        head->next = q;
    }
    return;
}


现在想想,这个命名也是十分恰当了。

第二种方法是:就地逆置法
与头插法十分类似,只不过是从是头结点后的第一个有效结点开始操作,完成后打印时,是从表尾开始打印

//就地逆置
//这里传入的是头结点的下一个有效结点
node *reverse_another(node *head){
       
    if(head == NULL || head->next == NULL)  //判定返回
        return head;
    
    node *rev,*t,*cur;
    rev = NULL;
    cur = head;
    while(cur != NULL){
     
        //指针后移
        t = cur;
        //向后遍历
        cur = cur->next;
        //与头插法类似
        t->next = rev;
        rev = t;
    }
    return rev;
}   

下面是测试用的主函数

int main(){
     
    node *head;
    int n;
    printf("请输入数字个数:");
    scanf("%d",&n);
    head = creat(n);
    print(head);
    //头插输出
    reverse_head(head);             
    //就地逆置输出,注意传入的是头结点后的第一个有效结点
    //head->next = reverse_another(head->next); 
    print(head);
    return 0;
}   

本来是要自己画图,但是发现有大佬画的十分清楚的图,便引用一下(懒了):

感谢大佬!!!!!
图片来源:https://blog.csdn.net/qq_42322103/article/details/82668765

图解:
刚开始是这样:
链表逆置的两种方法——头插法和就地逆置_第1张图片
循环前的操作
链表逆置的两种方法——头插法和就地逆置_第2张图片
进入循环,分别用q和p记录第一个和第二个节点
链表逆置的两种方法——头插法和就地逆置_第3张图片
链表逆置的两种方法——头插法和就地逆置_第4张图片
进入第二轮循环,这是发生重大变化的关键时期
链表逆置的两种方法——头插法和就地逆置_第5张图片
链表逆置的两种方法——头插法和就地逆置_第6张图片
链表逆置的两种方法——头插法和就地逆置_第7张图片
这张图调整一下
链表逆置的两种方法——头插法和就地逆置_第8张图片
直到链表为空

你可能感兴趣的:(数据结构,数据结构,C语言,链表)