(一)问题描述:
对一个单链表部分区域进行反转。要求编写函数输入链表;编写函数对链表部分区域进行反转;编写函数输出链表。【注意:仅允许使用malloc为n个结点指针分配内存以存储链表数据元素,其中n为第一行数据个数,不允许额外的malloc或者声明数组空间;仅允许操作结点指针,不允许更改结点数据元素如交换两个结点的数据元素;实现上述三个函数。】
(二)输入及输出要求和样例展示:
【输入形式】第一行若干个整数为链表数据元素,中间以空格隔开。第二行正整数 i 和 j ,表示将链表从第 i 个结点到第 j 个结点进行反转,中间以空格隔开。
【输出形式】若干个整数表示反转后的链表数据元素排列,中间以空格隔开。
【样例输入】
1 2 3 4 5
2 4
【样例输出】
1 4 3 2 5
(三)算法分析:
本题建立在对链表的建立、插入、删除等操作有了初步认识的基础上,进一步地训练对链表的综合运用能力。
本题主要需要解决以下问题:
【以下为程序分解展示,完整程序在底部】
(1)定义链表的结点类型。链表的结点包括输入的整数值(number)、第几个数(count)、链接指针(struct reverse *next)。
struct reverse{
int number;
int count;
struct reverse *next;
};
(2)利用尾插法,依次创建新的结点,并输入数字,得出是第几个数,存储到结构体中。
struct reverse *cre(void)
{
struct reverse *head, *p, *rear;
int number, cou = 1;
head = NULL;
do{
scanf("%d", &number);
p = (struct reverse *) malloc (sizeof(struct reverse));
p -> next = NULL;
p -> number = number;
p -> count = cou;
if(!head){
head = p;
}
else{
rear -> next = p;
}
rear = p;
cou += 1;
} while(getchar() != '\n');
return head;
}
(3)输入链表部分反转的范围,并按照算法【主体部分】将链表反转。
int main(void)
{
struct reverse *head, *ps, *pe, *pp, *pss, *temp;//创建需要的结构体指针
int start, end;
head = cre(); //创建链表
scanf("%d %d", &start, &end);
if(head == NULL) return 0; //假如链表是空的,直接结束
int volume = end - start; //用来判断需要处理几次
if(start == 1){ //假如start是链表头,以特殊方式处理
pp = head;
do{
temp = pp -> next; //temp为原本链表头的下一个结点
pp -> next = temp -> next; //先将原本链表头与temp的下一个结点连接
temp -> next = head; //将temp与当前head相连接
head = temp; //把链表头head变为temp
volume -= 1;
} while(volume > 0);
}
else{ //假如start不是第一个,直接处理
ps = head;
while(ps -> count != start - 1) ps = ps -> next; //ps指向start的前一个
pss = head;
while(pss -> count != start) pss = pss -> next; //pss指向start
pp = pss;
do{
temp = pss -> next; //与上述类似操作
pss -> next = temp -> next;
temp -> next = pp;
ps -> next = temp; //但要注意与前面的链表相连接
pp = temp; //pp移动到当前temp处
volume -= 1;
} while(volume > 0);
}
PrintList(head);
system("pause");
return 0;
}
(4)最终输出整个链表。
/*Traverse the linked list*/
void PrintList(struct reverse *head)
{
struct reverse *p = head;
while(p)
{
printf("%d ", p -> number);
p = p -> next;
}
}
(四)程序源码
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct reverse{
int number;
int count;
struct reverse *next;
};
struct reverse *cre(void)
{
struct reverse *head, *p, *rear;
int number, cou = 1;
head = NULL;
do{
scanf("%d", &number);
p = (struct reverse *) malloc (sizeof(struct reverse));
p -> next = NULL;
p -> number = number;
p -> count = cou;
if(!head){
head = p;
}
else{
rear -> next = p;
}
rear = p;
cou += 1;
} while(getchar() != '\n');
return head;
}
/*Traverse the linked list*/
void PrintList(struct reverse *head)
{
struct reverse *p = head;
while(p)
{
printf("%d ", p -> number);
p = p -> next;
}
}
int main(void)
{
struct reverse *head, *ps, *pe, *pp, *pss, *temp;//创建需要的结构体指针
int start, end;
head = cre(); //创建链表
scanf("%d %d", &start, &end);
if(head == NULL) return 0; //假如链表是空的,直接结束
int volume = end - start; //用来判断需要处理几次
if(start == 1){ //假如start是链表头,以特殊方式处理
pp = head;
do{
temp = pp -> next; //temp为原本链表头的下一个结点
pp -> next = temp -> next; //先将原本链表头与temp的下一个结点连接
temp -> next = head; //将temp与当前head相连接
head = temp; //把链表头head变为temp
volume -= 1;
} while(volume > 0);
}
else{ //假如start不是第一个,直接处理
ps = head;
while(ps -> count != start - 1) ps = ps -> next; //ps指向start的前一个
pss = head;
while(pss -> count != start) pss = pss -> next; //pss指向start
pp = pss;
do{
temp = pss -> next; //与上述类似操作
pss -> next = temp -> next;
temp -> next = pp;
ps -> next = temp; //但要注意与前面的链表相连接
pp = temp; //pp移动到当前temp处
volume -= 1;
} while(volume > 0);
}
PrintList(head);
system("pause");
return 0;
}