又是一次愉快的学校的oj作业题…
由于我实在是太懒了😭 一直到现在才更
话不多说上题目:
Problem A: 实验11_9_链表归并
已知有两个递增的正整数序列A和B,序列中元素个数未知,同一序列中不会有重复元素出现,有可能某个序列为空。现要求将序列B归并到序列A中,且归并后序列A的数据仍然按递增顺序排列。如果序列B中某些数据在序列A中也存在,则这些数据所在节点仍然留在序列B中,而不被归并到序列A中;否则这些数据所在节点将从序列B中删除,添加到序列A中。
要求:
建立两个单链表A、B用于存储两个正整数序列,然后按照题目的要求,将链表B中的元素归并到链表A中。在归并的过程中,不要释放B中的节点空间、然后建立新节点,而要改变指针的指向,使元素从B中删除并添加到A中。正整数序列按照递增顺序输入,用-1作为结束标志,注意-1不算这个正整数序列中的元素(不要统计-1)。在程序结束前要释放链表A、B中的所有节点。
Input
依次输入两个递增的正整数序列A和B,序列元素的个数未知,但以输入“-1”结束,每个正整数序列占一行。
Output
处理后的链表A中的元素,占一行;然后是处理后的链表B中的元素,占一行。每行的每个元素后有一个空格,注意最后一个元素后只有换行符,如果某个链表为空则,则输出“There is no item in X list.”
数据最多的测试用例节点数在100这个数量级,所有整数可以用int型存储。
请注意输入输出格式。
Sample Input Copy
Sample 1:
1 3 4 5 6 7 -1
2 3 6 8 9 10 11-1
Sample 2:
-1
-1
Sample Output Copy
Sample 1:
The new list A:1 2 3 4 5 6 7 8 9 10 11
The new list B:3 6
Sample 2:
There is no item in A list.
There is no item in B list.
我一开始看到这个题想着哈这不简单么 不就是个归并么 重新建立个表然后双管齐下看哪个大些不就行了么
然后眉头一皱 发现事情并不简单:直接对A操作!!不能建立一个新的表格!!!
我的思路是如果b的数据在a的两个相邻的数据之间,则插入进去
然后…
坑也许会迟到 但是绝对不会缺席 T-T
大概我踩进的坑有⬇️:
1、头插元素 因为原来的头节点没有元素 可以分类讨论来解决
但是我灵机一动 因为元素都是正整数,所以把头节点的元素初始化为0即可
2、尾插元素 同上 如果元素插在A的后面 “b的数据在a的两个相邻的数据”这个判准就不适用了 需要分类讨论
(后来发现可以模仿1的方法把尾巴数据定为2147483647就可了 只不过我的代码就没修改了)
3、一次插入多个元素 我一开始默认了两个元素之间只插入一个元素,然后光荣牺牲 后来改成while就可以了
上代码:/由于学校代码风格的要求加了一大堆注释…/
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}NODE;
typedef NODE* NODEPTR;
void createList(NODEPTR *headPtrPtr);//建立链表,并把第一个头节点的数据初始化为0减少讨论
void mergeList(NODEPTR *headPtrPtrA, NODEPTR *headPtrPtrB);//合并链表
void printListA(NODEPTR *headPtrPtr);//打印A链表
void printListB(NODEPTR *headPtrPtr);//打印B链表
void freeList(NODEPTR *headPtrPtr);//释放链表
int main()
{
NODE *headA, *headB;
createList(&headA);//建立A链表
createList(&headB);//建立B链表
mergeList(&headA, &headB);//合并链表
printListA(&headA);//打印A链表
printListB(&headB);//打印B链表
freeList(&headA);//释放A链表
freeList(&headB);//释放B链表
return 0;
}
void createList(NODEPTR *headPtrPtr)
{
int num;
NODEPTR currentPtr, previousPtr;
(*headPtrPtr) = malloc(sizeof(NODEPTR));
previousPtr = (*headPtrPtr);
previousPtr -> next = NULL;
previousPtr -> data = 0;
scanf("%d", &num);
while(num!=-1)
{
currentPtr = malloc(sizeof(NODEPTR));
currentPtr -> data = num;
currentPtr -> next = NULL;
previousPtr -> next = currentPtr;
previousPtr = currentPtr;
scanf("%d", &num);
}
}
void mergeList(NODEPTR *headPtrPtrA, NODEPTR *headPtrPtrB)
{
NODEPTR pA, pB, preB;
pA = *headPtrPtrA;
preB = *headPtrPtrB;
pB = preB -> next;
while(pA!=NULL && pB!=NULL)
{
if(pA->next == NULL)//如果A在尾节点上
{
if(pA->data==pB->data)//如果数据相同则后移B指针
{
preB = pB;
pB = preB -> next;
}
while(pB != NULL && pA->data<pB->data)//可以插到A的后面
{
preB -> next = pB -> next;
pB -> next = pA -> next;
pA -> next = pB;
pB = preB -> next;
pA = pA -> next;
}
}
else
{
while(pB!=NULL && pA->data <= pB -> data && pB->data<pA->next->data)//如果B的数据在A的两个数据之间
{
if(pA->data==pB->data)//数据相同则后移B指针
{
preB = preB -> next;
pB = preB -> next;
}
else
{
preB -> next = pB -> next;
pB -> next = pA -> next;
pA -> next = pB;
pB = preB -> next;
pA = pA -> next;
}
}
}
pA = pA ->next;
}
}
void printListA(NODEPTR *headPtrPtr)
{
NODEPTR currentPtr;
currentPtr = (*headPtrPtr) -> next;
if(currentPtr==NULL) printf("There is no item in A list.\n");
else
{
printf("The new list A:");
while(currentPtr!=NULL)
{
printf("%d ", currentPtr->data);
currentPtr = currentPtr -> next;
}
printf("\n");
}
}
void printListB(NODEPTR *headPtrPtr)
{
NODEPTR currentPtr;
currentPtr = (*headPtrPtr) -> next;
if(currentPtr==NULL) printf("There is no item in B list.\n");
else
{
printf("The new list B:");
while(currentPtr!=NULL)
{
printf("%d ", currentPtr->data);
currentPtr = currentPtr -> next;
}
printf("\n");
}
}
void freeList(NODEPTR *headPtrPtr)
{
NODEPTR currentPtr, nextPtr;
currentPtr = (*headPtrPtr);
while(currentPtr!=NULL)
{
nextPtr = currentPtr -> next;
free(currentPtr);
currentPtr = nextPtr;
}
return ;
}
Problem B: 实验11_15_拆分链表
已知有一个乱序的字符序列L,序列中的字符可能是英文字母、数字字符或其它字符,字符的个数未知,每个字符之间用空格分开。字符序列用“-1”作为输入结束标志,这里你要把-1当做一个字符串对待,并且不算作字符序列中的元素。如下即为一个合法的字符序列:“a c 3 b a d 6 , & j m 8 7 2 V -1”。你的任务是将这个字符序列拆分为三个独立的序列A、B和C,其中序列A存放序列L中的字母,序列B存放序列L中的数字,序列C存放序列L中的其他字符,然后,将序列A、B和C分别按照ASCII码的大小关系进行升序排序。最终序列L将变为空序列。
要求:
建立四个单链表,分别存储序列L、A、B、C中的元素。字符序列的输入用“-1”作为结束标志。建立链表L时,建议使用scanf(“%s”,s);来读取字符序列中的字符,即把单独的字符看做一个字符串读取。当L建立后,你要按照问题描述中所述,将L拆分为A、B、C三个链表,然后对每个链表都进行排序,这部分的操作都应该是对指针进行修改,而不是删除节点与建立新节点。在程序结束前要释放链表A、B、C中的所有节点。
Input
一个乱序的字符序列,序列元素的个数未知,以输入“-1”结束,输入“-1”前可能没有其它元素,每个字符序列占一行。
Output
链表A中的元素,占一行;然后是链表B中的元素,占一行。最后是链表C中的元素,占一行。每行的每个元素后有一个空格,注意最后一个元素后只有换行符,如果某个链表为空则,则输出“There is no item in X list.”
数据最多的测试用例节点数在100这个数量级。
请注意输入输出格式。
Sample Input Copy
Sample 1:
a c 3 b a d 6 , & j m 8 7 2 V -1
Sample 2:
z m v 1 a K 2 m p 9 a 0 a d -1
Sample Output Copy
Sample 1:
The list A is: V a a b c d j m
The list B is: 2 3 6 7 8
The list C is: & ,
Sample 2:
The list A is: K a a a d m m p v z
The list B is: 0 1 2 9
There is no item in C list.
第二题除了麻烦真的没有别的要注意的点了… 可能的坑都帮你挑明了
本来还担心数字有多位数的来着 后来发现都是“字符” 就放心大胆的写了
但是代码由于不给用全局变量写了好多二重指针…
看着别烦😂(但我自己都烦)
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
char symbol;
struct node *next;
}NODE;
typedef NODE* NODEPTR;
void createListHead(NODEPTR *headPtrPtr);//创建链表头
void createList(NODEPTR *headPtrPtr);//建立总链表
void printList(NODEPTR *headPtrPtr, char ListName);//打印链表
void splitList(NODEPTR *head);//把链表拆分
void engraft(int num, NODEPTR *Ptr, NODEPTR *nextPtr);//把总元素接到第num个链表的后面
void findmin(NODEPTR *findPtrPtr, NODEPTR *locationPtrPtr, NODEPTR *preLocationPtrPtr, char minSymbol);//找到最小的元素
void select_sort(NODEPTR *headPtrPtr);//运用选择排序来给链表排序;
void freeList(NODEPTR *headPtrPtr);
int main()
{
int i;
NODEPTR head[4];
for(i=0;i<4;i++) createListHead(&head[i]);//创建链表头
createList(&head[0]);//建立总链表
splitList(head);//把链表拆分
for(i=1;i<=3;i++) //对某个链表
{
select_sort(&head[i]);//先排序
printList(&head[i], 'A'-1+i);//然后打印
freeList(&head[i]);//最后free掉
}
return 0;
}
void createListHead(NODEPTR *headPtrPtr)
{
(*headPtrPtr) = (NODEPTR)malloc(sizeof(NODEPTR));
(*headPtrPtr) -> next = NULL;
return ;
}
void createList(NODEPTR *headPtrPtr)
{
char s[5];
NODEPTR currentPtr, previousPtr;
previousPtr = (*headPtrPtr);
scanf("%s", s);
while(s[0]!='-' || s[1]!='1')
{
currentPtr = malloc(sizeof(NODEPTR));
currentPtr -> symbol = s[0];
currentPtr -> next = NULL;
previousPtr -> next = currentPtr;
previousPtr = currentPtr;
scanf("%s", s);
}
return ;
}
void engraft(int num, NODEPTR *Ptr, NODEPTR *nextPtr)
{
Ptr[0] -> next = (*nextPtr) -> next;
Ptr[num]->next = (*nextPtr);
(*nextPtr) -> next = NULL;
Ptr[num] = Ptr[num]->next;
(*nextPtr) = Ptr[0]->next;
}
void splitList(NODEPTR *head)
{
int i;
char temp;
NODEPTR Ptr[4], nextPtr;
for(i=0;i<=3;i++) Ptr[i] = head[i];
nextPtr = head[0] -> next;
while(nextPtr!=NULL)
{
temp = nextPtr -> symbol;
if((temp>='a'&&temp<='z')||(temp>='A'&&temp<='Z')) engraft(1, Ptr, &nextPtr);//把元素接到A链表的后面
else if(temp>='0' && temp<='9') engraft(2, Ptr, &nextPtr);//把元素接到B链表的后面
else engraft(3, Ptr, &nextPtr);//把元素接到C链表的后面
}
}
void findmin(NODEPTR *findPtrPtr, NODEPTR *locationPtrPtr, NODEPTR *preLocationPtrPtr, char minSymbol)
{
while((*findPtrPtr)->next != NULL)
{
if((*findPtrPtr)->next->symbol < minSymbol)
{
minSymbol = (*findPtrPtr)->next->symbol;
(*locationPtrPtr) = (*findPtrPtr) -> next;
(*preLocationPtrPtr) = (*findPtrPtr);
}
(*findPtrPtr) = (*findPtrPtr) -> next;
}
}
void select_sort(NODEPTR *headPtrPtr)
{
char minSymbol;
NODEPTR preCurrentPtr, currentPtr, locationPtr, preLocationPtr, findPtr, temp;
preCurrentPtr = (*headPtrPtr);
currentPtr = preCurrentPtr -> next;
while(currentPtr!=NULL && currentPtr->next != NULL)
{
minSymbol = currentPtr -> symbol;
findPtr = currentPtr;
preLocationPtr = preCurrentPtr;
locationPtr = currentPtr;
findmin(&findPtr, &locationPtr, &preLocationPtr, minSymbol);
if(locationPtr!=currentPtr)//如果当前节点不是最小的
{
if(preLocationPtr==currentPtr)//如果最小的和当前的节点是相邻的
{
currentPtr->next = locationPtr->next;
preCurrentPtr -> next = locationPtr;
locationPtr->next = currentPtr;
}
else//如果最小的和当前的节点不是相邻的
{
temp = locationPtr -> next;
preCurrentPtr->next = locationPtr;
locationPtr -> next = currentPtr -> next;
preLocationPtr -> next = currentPtr;
currentPtr -> next = temp;
}
}
preCurrentPtr = preCurrentPtr -> next;
currentPtr = preCurrentPtr -> next;
}
return ;
}
void printList(NODEPTR *headPtrPtr, char ListName)
{
NODEPTR currentPtr;
currentPtr = (*headPtrPtr) -> next;
if(currentPtr==NULL) printf("There is no item in %c list.\n", ListName);
else
{
printf("The list %c is: ", ListName);
while(currentPtr!=NULL)
{
printf("%c ", currentPtr -> symbol);
currentPtr = currentPtr -> next;
}
printf("\n");
}
return ;
}
void freeList(NODEPTR *headPtrPtr)
{
NODEPTR currentPtr, nextPtr;
currentPtr = (*headPtrPtr);
while(currentPtr!=NULL)
{
nextPtr = currentPtr -> next;
free(currentPtr);
currentPtr = nextPtr;
}
}
结束咯~这次就两道题~轻轻松松~(误)