思路步骤:【括号()里面表示后续结点】
L:12345(5个结点)
设置p1=1(2345)
p2=2(345)//待处理的
L:1(2345)//1是倒置后的尽头,置空它的next指针
---------------
设置p1=3(45)//处理了2后剩下的
p2=2(1)//当前处理的是2,再接上已处理好的
L:12 //
p2=3(45)
-----------------
设置p1=4(5) //处理了3剩下的
p2=3(21) //当前处理的是3,再接上已处理好的
L:321//
p2=4(5)
-----------------
设置p1=5(NULL)
p2=4(321) //当前处理的是4,再接上已处理好的
L:4321 //
p2=5(NULL)
-----------------
设置p1=NULL
p2=5(4321)
L:54321 //当前处理的是4,再接上已处理好的
p2=NULL
-----------------判断到p1=NULL结束
#include <stdio.h>
#include <stdlib.h>
//不使用栈进行链表倒置
//创建一个链表
typedef struct Node
{
int data;
struct Node *next;
} Node, *LinkList;
//有头结点
void createLinkList1(int arr[], int len, LinkList L)
{
Node *p = L;
for (int i = 0; i < len; i++)
{
Node *n = (Node *)malloc(sizeof(Node));
n->data = arr[i];
n->next = NULL;
p->next = n;
p = n;
}
}
//有头结点的转置
void inverse1(LinkList L)
{
Node *p1 = L->next; //第一个
Node *p2 = p1->next; //第二个
L->next->next = NULL; //第1个=倒置后的最后1个,此结点没有下一个结点的指针,如2->1[->2->3..5]不成立
while (p1)
{
p1 = p2->next; //指向没有处理的结点的首个指针,如3->4->5、4->5
p2->next = L->next; //正在进行倒置处理的结点的下一个指向原来头结点的后一个,让它接上,如2后面接上1、3后面接上2->1
L->next = p2; //当前结点进行倒序,如头结点以外变成2->1、3->2->1
p2 = p1; //p2继续指向没有处理过的结点,如3->4->5、4->5
}
}
//无头结点
void createLinkList2(int arr[], int len, LinkList L)
{
Node *p = L;
for (int i = 1; i < len; i++)
{
Node *n = (Node *)malloc(sizeof(Node));
n->data = arr[i];
n->next = NULL;
p->next = n;
p = n;
}
}
//无头结点的转置,表头指针位置会被修改,要么使用引用要么返回结果重新接收
void inverse2(LinkList &L)
{
Node *p1 = L;
Node *p2 = p1->next;
L->next = NULL;
while (p1)
{
p1 = p2->next;
p2->next = L;
L = p2;
p2 = p1;
}
}
void display(LinkList L)
{
Node *p = L;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("------------------\n");
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
//有头结点
LinkList L1 = (LinkList)malloc(sizeof(Node));
createLinkList1(arr, 5, L1);
display(L1);
inverse1(L1);
display(L1);
//无头结点
LinkList L2 = (Node *)malloc(sizeof(Node));
L2->data = arr[0];
createLinkList2(arr, 5, L2);
display(L2);
inverse2(L2);
display(L2);
return 0;
}