源代码
#include <stdio.h>
#include <stdlib.h>
struct list
{
int data;
struct list *next;
};
struct list *create_list()//建立一个节点
{
//struct list *p = malloc(sizeof(struct list));
//p->data = 0;
//p->next = NULL;
//return p;
return (struct list *)calloc(sizeof(struct list), 1);
}
void traverse(struct list *ls)//循环遍历链表
{
struct list *p = ls;
while(p)
{
printf("%d\n", p->data);
p = p->next;
}
}
//第一个参数是链表的首节点,第二个参数是插入的位置,第三个参数是插入的值
struct list *insert_list(struct list *ls, int n, int data)//在指定位置插入元素
{
struct list *p = ls;
while (p && n--)
{
p = p->next;
}
//假设n大于链表里node的数量,那么下面的条件成立
if (p == NULL)//n大于链表节点数量,代表指定位置是个无效的位置
return NULL;
struct list *node = create_list();//创建一个新的节点
node->data = data;
node->next = p->next;
p->next = node;
return node;
}
void nizhi(struct list *ls) //逆置链表
{
struct list *p1 = ls;
struct list *p2 = ls->next;
struct list *p3;
struct list *last = ls->next;
while (p2)
{
p3 = p2->next;
p2->next = p1;
p1 = p2;
p2 = p3;
//printf("%d, %d\n", p1->data, p2->data);
}
last->next = NULL;
ls->next = p1;
}
int main(void)
{
struct list *first = create_list();//创建了一个首节点
int i;
for(i = 1; i < 10; i++)
{
insert_list(first, 0, i);
}
insert_list(first, 50, 100);
//clean_list(first);
traverse(first);
nizhi(first);
printf("------------\n");
traverse(first);
free(first);
return 0;
}
解析
上图是逆置前和逆置后指针指向的位置变化
首先要把先把前两个元素单独拿出来分别放到p1,p2里面去
p3 = p2->next;//存一下后一个元素的位置,以便p2向后移动的时候有下一个元素地址可以使用
p2->next = p1;//就是让后一个元素指向前一个元素,
p1 = p2; //p1往后移动一个元素
p2 = p3; //p2往后移动一个元素
至此,已经把一个元素的指针方向改变,并且p1,p2两个元素全部往后移动了一个元素
那使用一个while循环就可以把剩下的元素全部指向前一个
以p2为终止变量,因为当p2=p3的时候,p2已经是当前改变指针方向元素的next了,如果它是NULL,说明已经循环到了指针的末尾
while(p2) {
p3 = p2->next;
p2->next = p1;
p1 = p2;
p2 = p3;
}
此时,链表中的除首元素的外的元素已经全部指向的前一个元素,但是逆置前的第二个元素,也就是你逆置后的最后一个元素,也指向了首元素,那这就形成了一个环路。所以要把这个元素的next置为NULL。
但是逆置之后,已经没有办法得到这个元素的地址了,所以要在逆置前就把这个元素的地址存下来`struct list *last = ls->next;`
然后在逆置之后在把它指向NULL`last->next = NULL`;
切记,不能再逆置之前就把它指向NULL,因为那样,两边就只剩两个元素了。所以逆置的整个过程如下
void nizhi(struct list *ls)
{
if (ls->next == NULL || ls->next->next == NULL) //如果两边只有一个或者两个元素,逆置就没有意义,返回
return ;
struct list *p1 = ls;
struct list *p2 = ls->next;
struct list *p3;
struct list *last = ls->next;
while(p2) {
p3 = p2->next;
p2->next = p1;
p1 = p2;
p2 = p3;
}
last->next = NULL;
ls->next = p1;
}