4、单链表的算法之逆序
4.1、什么是链表的逆序
(1)链表的逆序又叫反向,意思就是把链表中所有的有效节点在链表中的顺序给反过来。
4.2、单链表逆序算法分析
(1)当我们对一个数据结构进行一个操作时,我们就需要一套算法。这就是数据结构和算法的关系。
(2)总结:算法有2个层次。第一个层次是数学和逻辑上的算法;第二次个层次是用编程语言来实现算法。
(3)从逻辑上来讲,链表的逆序有很多种方法。这些方法都能实现最终的需要,但是效率是不一样的。彼此的可扩展性、容错性等不同。
(4)思路:首先遍历原链表,然后将原链表中的头指针和头节点作为新链表的头指针和头节点,原链表中的有效节点挨个依次取出来,采用头插入的方法插入新链表中即可。
(5)链表逆序 = 遍历 + 头插入
4.3、编程实战
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
// 构建一个链表的节点
struct node
{
int data; // 有效数据
struct node *pNext; // 指向下一个节点的指针
};
// 作用:创建一个链表节点
// 返回值:指针,指针指向我们本函数新创建的一个节点的首地址
struct node * create_node(int data)
{
struct node *p = (struct node *)malloc(sizeof(struct node));
if (NULL == p)
{
printf("malloc error.\n");
return NULL;
}
// 清理申请到的堆内存
bzero(p, sizeof(struct node));
// 填充节点
p->data = data;
p->pNext = NULL;
return p;
}
// 将pH指向的链表逆序
void reverse_linkedlist(struct node *pH)
{
struct node *p = pH->pNext; // pH指向头节点,p指向第1个有效节点
struct node *pBack; // 保存当前节点的后一个节点地址
// 当链表没有有效节点或者只有一个有效节点时,逆序不用做任何操作
if ((NULL ==p) || (NULL == p->pNext))
return;
// 当链表有2个及2个以上节点时才需要真正进行逆序操作
while (NULL != p->pNext) // 是不是最后一个节点
{
// 原链表中第一个有效节点将是逆序后新链表的尾节点,尾节点的pNext指向NULL
pBack = p->pNext; // 保存p节点后面一个节点地址
if (p == pH->pNext)
{
// 原链表第一个有效节点
p->pNext = NULL;
}
else
{
// 原链表的非第1个有效节点
p->pNext = pH->pNext;
}
pH->pNext = p;
//p = p->pNext; // 这样已经不行了,因为p->pNext已经被改过了
p = pBack; // 走到下一个节点
}
// 循环结束后,最后一个节点仍然缺失
insert_head(pH, p);
}
int main(void)
{
reverse_linkedlist(pHeader);
printf("------------------逆序后-------------\n");
bianli2(pHeader);
return 0;
}