在头节点插入再反转
这部分代码是直接从头节点处采用首插法
全部代码
#include<stdio.h>
#include<stdlib.h>
/*
功能:反转链表(我们只是调整链接,节点的地址不变)
实现:通过遍历整个链表,来调整链接部分,使它指向上一个节点,而不是下一个节点
如果没有前一个节点,我们认为前一个节点为NULL;最后遍历到最后,把头指针放在最后
链表为空,或者链表只有一个节点这段代码都是可以实现的
*/
struct Node {
int date;
struct Node* next;
};
//写一个反转函数
/*
这里我们接受头节点的地址作为参数,然后在链表反转后,返回头节点的地址
*/
struct Node* Reverse(struct Node*head) {
struct Node* PrevNode=NULL;//上一个节点
struct Node* CurrentNode;//当前节点
CurrentNode = head;
struct Node* NextNode;//下一个节点
//遍历,因为我们在遍历的时候只能知道下一个节点,所以需要一个变量来存储上一个节点,还需要知道当前节点
while (CurrentNode != NULL) {
NextNode = CurrentNode->next;//首先把下一个节点信息(CurrentNode->next)存储在NextNode中
CurrentNode->next = PrevNode;//把当前节点的连接部分(CurrentNode->next)指向前一个节点(PrevNode)
PrevNode = CurrentNode;//上一个节点信息进行移动到当前节点
CurrentNode = NextNode;//当前节点移动到下一个节点
}
head = PrevNode;//此时,CurrentNode和NextNode都指向空,而PrevNode指向最后一个结点
return head;
}
struct Node* Insert(int x, struct Node*head)//插入这里我们需要地址传递
{
//定义一个临时变量来进行插入
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->date = x;
temp->next = NULL;
//接下来就是我们每次创建一个节点,都要进行插入,每次要把新创建的temp的地址给头指针,并且还有把头指针存储的下个节点的地址给temp的地址域
if (head != NULL) temp->next = head;//(这里是把首节点的地址给temp)
//接下来把temp的地址给head
head = temp;
return head;
}
void Print(struct Node* head)//这时需要传入头节点的值,是值传递
{
printf("链表是:");
while (head != NULL)
{
printf(" %d", head->date);
head = head->next;//这种方法对节点进行遍历
}
printf("\n");
}
int main(void) {
struct Node* head=NULL;//head作为了局部变量,head为全局变量的话反转函数就不是struct类型的了,而是空类型的 void
head = Insert(1, head);
head = Insert(5, head);
head = Insert(4, head);
head = Insert(7, head);
//打印链表
Print(head);
head = Reverse(head);
Print(head);
return 0;
}
运行结果
在任意位置插入再反转
这里的代码会更复杂一些,但是原理和之前的代码差不多,最后把相关信息打印
代码
#include<stdio.h>
#include<stdlib.h>
struct Node {
int date;
struct Node* next;
};
struct Node* Insert(struct Node* head, int x,int n) {
struct Node* temp=(struct Node*)malloc(sizeof(struct Node));
temp->date = x;
temp->next = NULL;
if (n == 1) {
//这里是头插法
temp->next = head;
head = temp;
printf("在头指针head插入,插入数据为:%d\n", head->date);
return head;
}
struct Node* listread=head;
for (int i = 0; i < n-2; i++)//这是遍历到了n-1个节点
{
listread = listread->next;
}
temp->next = listread->next;
listread->next = temp;
printf("在节点%d处插入,插入值为%d\n", n, temp->date);
return head;
}
void Print(struct Node* head) {
struct Node* Readlist;
Readlist = head;
printf("链表的信息为:");
while (Readlist != NULL) {
printf("%d ", Readlist->date);//打印的代码一定要写在遍历代码的前面
Readlist = Readlist->next;
}
printf("\n");
}
struct Node* Reverse(struct Node* head) {
struct Node* pre, * current, * next;
pre = NULL;
next = NULL;
current = head;
while (current != NULL) {
/*
这段代码的逻辑并不是简单的遍历
第一步:我们需要先保存下一个节点的地址
第二步:把当前节点.next指向前一个节点,进行反转
第三步:各个节点开始向后移动
*/
next= current->next;
current->next = pre;//这一步就先反转
//各个节点开始移动(移动方法,上一个节点移向当前节点;当前节点移动到下一个节点)
pre = current;
current = next;
}
//跳出循环的时候,current=NULL,next=NULL,这时刚好头指针指向pre
head = pre;
return head;
}
int main(void) {
struct Node* head=NULL;
head=Insert(head, 1, 1);
Print(head);
head = Insert(head, 3, 2);
Print(head);
head = Insert(head, 5, 1);
Print(head);
head = Insert(head, 4,2);
Print(head);
head=Reverse(head);
Print(head);
return 0;
}