关于单链表的反转的学习

最近在学习mooc网上的 陈越、何钦铭 老师的数据结构,在做作业的时候遇到单链表反转问题,于是就拉出来单独了解一下:

方法一:用数组下标模拟内存地址,代码如下:
/*
假设这里的地址不超过99999
输入规则:
 第一行:链表起始地址(head_position) 链表节点个数(node_num)
 后node_num行:本节点地址(position) 节点值(value) 下一个节点的地址(next)
 */
#include <stdio.h>
struct Node{
    // value是这个节点的值,position是模拟这个节点的地址,next是模拟这个节点的下一个地址
    // 假设每个节点在没有连起来的时候,next都是-1
    int value;
    int position;
    int next=-1;
};
typedef struct Node item;
// 用这个数组模拟内存
item item_list[100010];
void ReadLink(int head_node)
{
    while(head_node!=-1)
    {
        printf("%05d %d %05d \n",item_list[head_node].position, item_list[head_node].value, item_list[head_node].next);
        head_node = item_list[head_node].next;
    }
    printf("\n");
}
int main() {
    int head_position, node_num, next_position, value, position, tmp;
    // 已经知道首地址和一共有多少个节点
    scanf("%d %d", &head_position, &node_num);
    for (int i = 0; i < node_num; ++i) {
        // 记录每一个点的位置,值,和链接在这个点的下一个点的位置
        scanf("%d %d %d", &position, &value, &next_position);
        item_list[position].position = position;
        item_list[position].value = value;
        item_list[position].next = next_position;
    }
    printf("反转前:\n");
    ReadLink(head_position);
    int front, rear, p;
    // 初始化front为首节点的地址,rear为第二个节点的位置,要反转这两个节点,需要把第二个节点的next指向前一个点
    // 但是如果直接修改,原来的第二个节点的next节点就找不到了,因此要先记录一下第二个节点的next
    // 这里的head_position和item_list[head_position].position是相同的,方便理解因此写成后者
    front = item_list[head_position].position;
    rear = item_list[item_list[head_position].next].position;
    // 反转的时候,两个节点反转一次,
    // 每次都要把后面节点的next保存一下,然后把后面节点的next赋值为前面节点的位置
    // 再重新初始化front和rear两个值
    while(rear!=-1) {
        p = item_list[rear].next;
        item_list[rear].next = item_list[front].position;
        front = rear;
        rear = p;
        // printf("%05d\n", rear);
    }
    // 处理一下原来的头节点
    item_list[head_position].next = -1;
    printf("反转后:\n");
    ReadLink(front);
}

/*
00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
 */

输出:
反转前:
00100 1 12309 
12309 2 33218 
33218 3 00000 
00000 4 99999 
99999 5 68237 
68237 6 -0001 

反转后:
68237 6 99999 
99999 5 00000 
00000 4 33218 
33218 3 12309 
12309 2 00100 
00100 1 -0001 
方法二:用指针操作单链表:
#include <stdio.h>
#include<stdlib.h>
typedef struct Node* ptrNode;
struct Node{
    int val;
    ptrNode next;
};
void ReadLink(ptrNode front)
{
    while(front!=NULL){
        printf("%d ", front->val);
        front = front->next;
    }
    printf("\n");
}
int main()
{
    int node_num, val;
    ptrNode front, rear;
    rear = (ptrNode)malloc(sizeof(struct Node));
    rear->next = NULL;
    front = rear;
    // 输入节点的个数
    scanf("%d", &node_num);
    for (int i = 0; i < node_num; ++i) {
        scanf("%d", &val);
        ptrNode p = (ptrNode)malloc(sizeof(struct Node));
        p->val = val;
        p->next = NULL;
        rear->next = p;
        rear = p;
    }
    ptrNode p;
    printf("反转前:\n");
    ReadLink(front->next);
    front = front->next;
    rear = front->next;
    // 处理一下头节点
    front->next = NULL;
    while(p!=NULL){
        p = rear->next;
        rear->next = front;
        front = rear;
        rear = p;
    }
    free(p);
    printf("反转后:\n");
    ReadLink(front);
}
输出
5
2 4 6 8 10
反转前:
2 4 6 8 10 
反转后:
10 8 6 4 2 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值