上课忙于种大树(树和二叉树),实验回到链表间
首先先温习一下👉数据结构 线性表、链表 学习心得代码
一、题目与分析:
给定一个单链表 L1→L2→⋯→Ln−1→Ln,请编写程序将链表重新排列为 Ln→L1→Ln−1→L2→⋯。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N (≤105)。结点的地址是5位非负整数,NULL地址用−1表示。
接下来有N行,每行格式为:
Address Data Next
其中Address
是结点地址;Data
是该结点保存的数据,为不超过105的正整数;Next
是下一结点的地址。题目保证给出的链表上至少有两个结点。
输出格式:
对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
68237 6 00100
00100 1 99999
99999 5 12309
12309 2 00000
00000 4 33218
33218 3 -1
二、代码分析
1.草创大业
从左到右依次是输入内容、中间内容、输出内容,输入之后,需要先对数据进行一个处理,这里因为地址和下一个地址,因而我选择了线性表(数组)储存,数组的优点就是可以用下标来储存数据和下一个地址,储存之后再从线性表输入链表。
这里运用了链表和线性表,两个数据结构,输入的内容先用线性表收集处理。
typedef struct Node {
int no; //地址
int data; //数据
int non; //下一个地址
struct Node* next; //后
struct Node* front; //前
} Node;
typedef struct {
//int add[100001]; //地址
int data[100001]; //数据
int next[100001]; //下一个地址
int first;
}SqList;
2.函数设计
I.数组读入到链表
采用尾插法,从数组读入内容,尾插时记录读入个数,方便统计下面打印时的个数,具体读入思路就是:“首地址”或是从“上一个结点的下一个地址”得到下一个数据的地址,从sq[该地址]读入新建结点的data与下一个地址,链接此结点。当发现下一个地址是-1的时候,结束读入,读入完毕,返回读入个数。
int CreateTail(Node *head, SqList *sq,int num){ //尾插
Node * r,* newNode;
r = head;
r->non = sq->first; //下一个地址
int flag = 0;
for(int i = 1;i<=num;i++){
if(r->non == -1) {
r->next = NULL;
return flag;
}
newNode = (Node *)malloc(sizeof (Node));
newNode->data = sq->data[r->non];
newNode->non = sq->next[r->non];
newNode->no = r->non;
r->next = newNode;
newNode->front = r;
r = newNode;
flag++;
}
r->next = NULL;
return flag;
}
II. 重排
这里我新建了一个NEW链表在主函数,来接收重排的内容,采用了一个i变量,通过奇数、偶数判断重排是应当从头还是从尾加入( L1→L2→⋯→Ln−1→Ln,到Ln→L1→Ln−1→L2→⋯都是尾一个头一个的顺序)。
void ChangeArray(Node *head, Node *CA, int num){
Node *front, *tail, *change, *newNode;
front = tail = head->next;
change = CA;
while(tail->next){
tail = tail->next;
}
for(int i=1; i<=num; i++){
newNode = (Node *) malloc(sizeof(Node));
if(i%2 != 0) {
newNode->no = tail->no;
newNode->data = tail->data;
newNode->non = front->no;
newNode->front = change;
newNode->next = change->next;
change->next = newNode;
change = newNode;
if(tail->front != head)
tail = tail->front;
}
else{
newNode->no = front->no;
newNode->data = front->data;
newNode->non = tail->no;
newNode->front = change;
newNode->next = change->next;
change->next = newNode;
change = newNode;
if(front->next != NULL)
front = front->next;
}
}
}
III.打印输出
由于起初输入的地址不是字符串(因为00000输入可以变为0,00100变为100,方便前面代码的比较寻找),所以写了一个节点内容打印,来补全0的个数(略微屎山代码,请理解),另外的正常打印代码可在此学到(克隆)——数据结构 线性表、链表 学习心得代码
void NodePrint(int address, int data, int nextadd){
if(address == -1)
return;
if(address>=10000)
printf("%d ",address);
else if(address >= 1000)
printf("0%d ",address);
else if(address >= 100)
printf("00%d ",address);
else if(address >= 10){
printf("000%d ",address);
}
else if(address >= 0){
printf("0000%d ",address);
}
printf("%d ",data);
if(nextadd>=10000 || nextadd == -1)
printf("%d\n",nextadd);
else if(nextadd >= 1000)
printf("0%d\n",nextadd);
else if(nextadd>= 100)
printf("00%d\n",nextadd);
else if(nextadd >= 10){
printf("000%d\n",nextadd);
}
else if(nextadd >= 0){
printf("0000%d\n",nextadd);
}
}
int print(Node *head, int N) { //打印
Node *p;
p = head->next;
if(p == NULL) {
printf("NULL");
return 1;
}
for(int i = 0;i < N;i++) {
if(i == N-1)
NodePrint( p->no, p->data, -1);
else NodePrint( p->no, p->data, p->non);
p = p->next;
}
return 0;
}
3.主函数
这里没有什么可以写的,对于函数的调用,以及传参需要注意一下。
int main(){
Node L;
Node New;
SqList sq;
int first,N;
scanf("%d %d",&first,&N);
sq.first = first;
for(int i = 1; i <= N; i++){
int address,next_address,x;
scanf("%d %d %d",&address,&x,&next_address);
sq.data[address] = x;
sq.next[address] = next_address;
}
int fl = CreateTail(&L,&sq,N);
//print(&L, fl);printf("\n");
ChangeArray(&L, &New, N);
print(&New, fl);
}
三、成功与复盘
一顿操作,全部通过,flag的设置是为了防第三个检查点,给线性表开很大空间是防第四个(空间换时间,起初本打算挨个存,就是最开始定义线性表的被注释的那个地址一行,但是这样每次写入链表都要遍历一次线性表,时间比较长)。
蛮屎山的,希望有更优解。
四、全代码展示
//
// Created by DDD on 2023/11/4.
//
#include <stdio.h>
#include <malloc.h>
typedef struct Node {
int no; //地址
int data; //数据
int non; //下一个地址
struct Node* next; //后
struct Node* front; //前
} Node;
typedef struct {
//int add[100001]; //地址
int data[100001]; //数据
int next[100001]; //下一个地址
int first;
}SqList;
int CreateTail(Node *head, SqList *sq,int num){ //尾插
Node * r,* newNode;
r = head;
r->non = sq->first; //下一个地址
int flag = 0;
for(int i = 1;i<=num;i++){
if(r->non == -1) {
r->next = NULL;
return flag;
}
newNode = (Node *)malloc(sizeof (Node));
newNode->data = sq->data[r->non];
newNode->non = sq->next[r->non];
newNode->no = r->non;
r->next = newNode;
newNode->front = r;
r = newNode;
flag++;
}
r->next = NULL;
return flag;
}
void ChangeArray(Node *head, Node *CA, int num){
Node *front, *tail, *change, *newNode;
front = tail = head->next;
change = CA;
while(tail->next){
tail = tail->next;
}
for(int i=1; i<=num; i++){
newNode = (Node *) malloc(sizeof(Node));
if(i%2 != 0) {
newNode->no = tail->no;
newNode->data = tail->data;
newNode->non = front->no;
newNode->front = change;
newNode->next = change->next;
change->next = newNode;
change = newNode;
if(tail->front != head)
tail = tail->front;
}
else{
newNode->no = front->no;
newNode->data = front->data;
newNode->non = tail->no;
newNode->front = change;
newNode->next = change->next;
change->next = newNode;
change = newNode;
if(front->next != NULL)
front = front->next;
}
}
}
void NodePrint(int address, int data, int nextadd){
if(address == -1)
return;
if(address>=10000)
printf("%d ",address);
else if(address >= 1000)
printf("0%d ",address);
else if(address >= 100)
printf("00%d ",address);
else if(address >= 10){
printf("000%d ",address);
}
else if(address >= 0){
printf("0000%d ",address);
}
printf("%d ",data);
if(nextadd>=10000 || nextadd == -1)
printf("%d\n",nextadd);
else if(nextadd >= 1000)
printf("0%d\n",nextadd);
else if(nextadd>= 100)
printf("00%d\n",nextadd);
else if(nextadd >= 10){
printf("000%d\n",nextadd);
}
else if(nextadd >= 0){
printf("0000%d\n",nextadd);
}
}
int print(Node *head, int N) { //打印
Node *p;
p = head->next;
if(p == NULL) {
printf("NULL");
return 1;
}
for(int i = 0;i < N;i++) {
if(i == N-1)
NodePrint( p->no, p->data, -1);
else NodePrint( p->no, p->data, p->non);
p = p->next;
}
return 0;
}
int main(){
Node L;
Node New;
SqList sq;
int first,N;
scanf("%d %d",&first,&N);
sq.first = first;
for(int i = 1; i <= N; i++){
int address,next_address,x;
scanf("%d %d %d",&address,&x,&next_address);
sq.data[address] = x;
sq.next[address] = next_address;
}
int fl = CreateTail(&L,&sq,N);
//print(&L, fl);printf("\n");
ChangeArray(&L, &New, N);
print(&New, fl);
}
return 0; //一树梨花落晚风