- 算法分析
利用指针改指来实现表逆置。
- 当链表为空的时候,就是它本身
- 当链表有两个以上结点的时候,将链表处理为只含有一个结点的带头结点链表,和剩余结点组成的链表
操作:通过指针改指实现
1.当链表为空或只含有一个结点时,链表逆置与原链表相同;
2.当含有两个或两个以上结点时,将链表处理成只含第一个结点的带头结点链表和一个无头结点的包含剩余结点的链表,然后从无头结点的链表上摘下,头插*/
#include<stdio.h>
#include <stdlib.h>
//定义链表结点结构
typedef struct Node {
int data;
struct Node* next;
}Node;
//定义单链表
typedef Node* LinkList;
//尾插法创建单链表
void CreatList(LinkList *L,int n) {
LinkList p, r;
*L= (LinkList)malloc(sizeof(Node)); //头结点
r = *L; //r指向链表尾结点,这时r是第一个也是最后一个
printf("请输入链表元素:\n");
for (int i = 0; i < n; i++) {
p = (Node*)malloc(sizeof(Node)); //为新结点申请内存
scanf("%d", &p->data);
r->next = p;
r = p;
}
r->next = NULL;
}
//输出链表
void Printlist(LinkList L)
{
LinkList p;
p = L->next; //p指向L的第一个结点
while (p) {
printf("%d", p->data);
p = p->next;
}
}
//就地逆置
void Reverselist(LinkList *L) {
Node *p, *q;
if ((*L)->next && (*L)->next->next) { //如果链空或链表只有一个结点,则不需要翻转
p = (*L)->next; //将链表分为两个,一个带头结点和一个结点的链表,和剩余 结点组成的链表
q = p->next;
p->next = NULL;
while (q) { //用头插法依次将第二个链表中的结点插入第一个链表
p = q;
q = q->next;
p->next = (*L)->next;
(*L)->next = p;
}
}
}
int main(void) {
LinkList L;
int len;
printf("请输入链表长度");
scanf("%d", &len);
CreatList(&L, len);
Reverselist(&L);
printf("翻转后:\n");
Printlist(L);
return 0;
}
- 运行结果
- 学习心得:
学习了单链表的基本操作和单链表位置变换。
对于LinkList L: L是指向定义的node结构体的指针,可以用->运算符来访问结构体成员,即L->elem,而(*L)就是个Node型的结构体了,可以用点运算符访问该结构体成员,即(*L).elem。
对于LinkList *L:L是指向定义的Node结构体指针的指针,所以(*L)是指向Node结构体的指针,可以用->运算符来访问结构体成员,即(*L)->elem,当然,(**L)就是Node型结构体了,所以可以用点运算符来访问结构体成员,即(**L).elem。