一:什么是链表的逆序
(1)链表的逆序又叫反向,意思就是把链表中所有的有效节点在链表中的顺序给反过来
二:单链表逆序算法分析
(1)当需要对一个数据结构进行操作时,就有必要有一套算法。这就是数据结构和算法的关系
(2)算法的两个层次:第一个层次是数学和逻辑上的算法;第二个层次是编程语言来实现算法
(3)从逻辑上来讲,链表的逆序有很多种方法。这些方法最终都能实现需要,但是效率是一样的。彼此的可扩展性容错性等不同
(4)思路:首先先遍历节点,然后将原链表中的头指针头节点作为新链表的头指针头节点,再将原链表中的有效节点挨个依次取出来,采用头部插入的方法插入进新链表
(5)链表逆序 = 遍历 + 头插入
三:逆序代码实现
(1)实现函数
/****************************************
函数名:reverse
作用:将链表进行反向排序
返回值:无
参数:ph 链表头指针
****************************************/
void reverse(struct node *ph)
{
strucct node *p = ph->pNEXT;
STRUCT NODE *pback = ph;
if((p == NULL) || (p->pNEXT == NULL)) //判断是否是只有一个节点还是没有有效节点
{
return; //当链表中只有一个节点或没有有效节点时不需要操作
}
//当链表有两个或两个以上的节点才需要进行操作
while(NULL != p->pNEXT) //判断是不是最后一个节点
{
back = p->pNEXT; //保存p节点后的一个节点
if(p == ph->pNEXT)
{
//原链表的第一个有效节点,在逆序之后会变成尾节点,将这个节点的
//指针指向NULL
p->pNEXT = NULL;
}
else
{
//不是原链表的第一个有效节点,指向上一个头节点指向的节点地址
p->pNEXT = ph->pNEXT;
}
ph->pNEXT = p; //头节点指向新插入的节点
p = pback; //将下一个要插入的节点的地址给指针临时变量
}
//在进行遍历时判断条件是不是最后一个节点,这样会丢失最后一个节点
insert_head(ph,p->pNEXT);
}
(2)程序源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node
{
int datas;
struct node *pNEXT;
};
struct node *create(int a)
{
struct node *p = (struct node *)malloc(sizeof(struct node));
if(NULL == p)
{
printf("malloc error!\n");
return NULL;
}
memset(p,0,sizeof(struct node));
//bzero(p,sizeof(struct node));
p->datas = a;
p->pNEXT = NULL;
return p;
}
void insert_tail(struct node *phead,struct node *new)
{
struct node *p = phead;
int cat = 0;
while(NULL != p->pNEXT)
{
p = p->pNEXT;
cat++;
}
p->pNEXT = new;
phead->datas = cat +1;
}
void insert_head(struct node *head,struct node *new)
{
new->pNEXT = head->pNEXT;
head->pNEXT = new;
head->datas += 1;
}
void ergodic(struct node *ph)
{
struct node *p = ph;
int cat = 0;
printf("datas number is a: %d\n",p->datas);
while(NULL != p->pNEXT)
{
cat++;
printf("datas number is :%d\n",cat);
p = p->pNEXT;
printf("datas is: %d\n",p->datas);
}
}
int delete(struct node *ph,int data)
{
struct node *p = ph;
struct node *prev = NULL;
int cat = 0;
while(NULL != p->pNEXT)
{
prev = p;
p = p->pNEXT;
if(p->datas == data)
{
if(NULL == p->pNEXT)
{
prev->pNEXT = NULL;
free(p);
cat = ph->datas;
ph->datas = cat -1;
}
else
{
prev->pNEXT = p->pNEXT;
free(p);
cat = ph->datas;
ph->datas = cat -1;
}
return 0;
}
}
return -1;
}
void reverse(struct node *ph)
{
strucct node *p = ph->pNEXT;
STRUCT NODE *pback = ph;
if((p == NULL) || (p->pNEXT == NULL)) //判断是否是只有一个节点还是没有有效节点
{
return; //当链表中只有一个节点或没有有效节点时不需要操作
}
//当链表有两个或两个以上的节点才需要进行操作
while(NULL != p->pNEXT) //判断是不是最后一个节点
{
back = p->pNEXT; //保存p节点后的一个节点
if(p == ph->pNEXT)
{
//原链表的第一个有效节点,在逆序之后会变成尾节点,将这个节点的
//指针指向NULL
p->pNEXT = NULL;
}
else
{
//不是原链表的第一个有效节点,指向上一个头节点指向的节点地址
p->pNEXT = ph->pNEXT;
}
ph->pNEXT = p; //头节点指向新插入的节点
p = pback; //将下一个要插入的节点的地址给指针临时变量
}
//在进行遍历时判断条件是不是最后一个节点,这样会丢失最后一个节点
insert_head(ph,p);
}
int main(void)
{
struct node *phead = create(0);
insert_tail(phead,create(12));
insert_tail(phead,create(13));
insert_tail(phead,create(14));
ergodic(phead); //遍历打印各个节点数据区
reverse(phead); //将链表进行逆序
ergodic(phead); //再次遍历打印各个节点数据区
return 0;
}
运行结果: