就地逆置的时候,若操作对象为顺序表,可直接用类似于数组交换的方式来进行数据逆置。因为顺序表的结构是顺序排列,用这种方式很容易实现。若是操作对象是单链表,需要用到摘点的方式进行操作。
具体是:将原有链表中的结点依次摘下,然后用头插法依次建立,这样建出的新表刚好使所有结点就地逆置,且不需要开辟新的结点。
还有一点,我看到课本上说,对单链表中的元素逆置交换,则不能按照“交换”思路进行,因为对于链表中的第i结点需要顺链查找第n-i+1(链表察度为n)个结点,逆置链表的复杂度将达到O(n*2)。
也就是说,单链表用“交换”的方法是可行的,只是时间复杂度会很大罢了。但是,我不知道这种方法该如何实现,因为不知道怎么具体确定到某一个结点,怎么去实现这个循环。若有兴趣的朋友有看到,希望能指点我一二。
另外,对于双向链表,用“交换”的方式会很简单,这里也就不多说了。
接下来,展示一下单链表摘点方法实现的就地逆置代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct Node {
int data;
struct Node* next;
}Node,*Seq;
void Create(Seq L);
void Rever_1(Seq L);
void Rever_2(Seq L);
int main() {
Seq L;
Node* p;
L = (Node*)malloc(sizeof(Node));
printf("请输入L链表的值:");
Create(L);
p = L->next;
printf("L链表创建后的值:");
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
Rever_1(L);
printf("输出L表就地逆置的结果:");
p = L->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
}
void Create(Seq L) {
Node* p, *s;
p = L;
int c;
scanf("%d", &c);
while (c != -1) {
s = (Node*)malloc(sizeof(Node));
s->data = c;
p->next = s;
p = s;
scanf("%d", &c);
}
p->next = NULL;
}
void Rever_1(Seq L) {
Node* p, * q;
p = L->next;
L->next = NULL;
while (p != NULL) {
q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
}
结果如下: