习题一:
- 问题描述
假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,并要求利用原表(即A表和B表的)结点空间存放表C。 - 输入格式
输入的第一行表示测试数据的组数T
后面跟着T组输入
每组测试数据占三行 - 输出格式
返回链表A和B按照上述要求处理后形成的链表C的遍历结果,链表C按元素值递减有序排列,长度为lenC(lenC = lenA + lenB)。输出时链表C每个元素之间用空格进行分割,并且最后要换行! - 备注
1、使用原表A和B的节点空间存放C。
2、写清楚注释,让审核人能理解你的思路(代码通过并且有详细的注释这题才会给满分)。
3、必须按照题目要求进行排序,不得通过数组排序来获取结果!
下面展示一些 。
输入样例
2
5 5
1 2 3 4 5
1 2 3 4 5
3 3
2 4 8
3 6 9
输出样例
5 5 4 4 3 3 2 2 1 1
9 8 6 4 3 2
代码实例。
#include <stdio.h>
#include <stdlib.h>
#define MAXINT 100
typedef struct Node {
int data ;
struct Node* next ;
}Node;
typedef struct Node* LinkList ;
//打印一个单链表
void ShowList(LinkList l) {
LinkList p ;
p = (LinkList)malloc(sizeof(Node));
p = l->next ;
while(p != NULL){
printf("%d ", p->data) ;
p = p->next ;
}
}
//创建一个单链表
LinkList CreatLinkList(int n) {
Node *h, *p, *q ; //设置三个结点,h保存la的头节点,q一直指向la的尾结点,p存储输入数据;
h = (LinkList)malloc(sizeof(Node));
h->next = NULL ; //初始化链表 ,让它成为一个空表
q = h ; //开始时la的头结点与尾结点重合
int i ;
for (i = 0; i < n; i ++) {
p = (LinkList)malloc(sizeof(Node)) ;
scanf("%d", &p->data) ;
p->next = q->next ;
q->next = p ;
q = p ;
}
return h ;
}
//倒置链表中的数据
LinkList ReverseList(LinkList l) {
Node *p, *q ; //设置两个结点
p = l->next ; //p是l的第一个数据结点
l->next = NULL ; //将l移位指向链表末尾的结点,我们在l的后面重新将原本的数据插入,构成一个新的逆置链表
while(p){
q = p->next ; //将p的下一位结点保存在q中
p->next = l->next ;
l->next = p ; //将p插入在L之后
p = q ;//完成p的后移
}
return l ;
}
//按照递增顺序并置两个链表,最后转置数据
LinkList MergeList(LinkList la, LinkList lb) {
LinkList pa, pb;
pa = la->next; //pa和pb分别指向la和lb的第一个数据结点
pb = lb->next;
LinkList pc = la;//以La的头结点为并置的头结点
while(pa && pb){
if(pa->data <= pb->data)//pa里数据比pb小,就连接pa指向的结点,pa指向la的后一个
{
LinkList qa = pa->next; //存储pa下一个结点的数据
pa->next = NULL; //将pa指针直接指向la的末尾,相当于将pa->data这个元素从队列中分离出来
pc->next = pa; //pc是一个准备摘取数据的指针,当pa小时,pc就指向pa,将已经摘取出的元素放在自己的链表里
pc = pc->next;
pa = qa; //pa指针后移一个位置
}
else{//pb里数据较小,就连接pb指向的结点,pb指向lb的后一个,同理
LinkList qb = pb->next;
pb->next = NULL;
pc->next = pb;
pc = pc->next;
pb = qb;
}
}
pc->next = pa ? pa : pb;//合并剩下的没遍历完的部分
return la;
}
LinkList ProjectEntrance() {
int n1, n2 ;
scanf("%d %d", &n1, &n2) ;
LinkList la ;
LinkList lb ;
la = CreatLinkList(n1) ; //创建链表并输入数据
lb = CreatLinkList(n2) ;
LinkList lc ;
lc = MergeList(la, lb) ; //按照原有顺序并置两个列表
return lc ;
}
int main() {
LinkList l[MAXINT] ;
int i, j, n ;
scanf("%d", &n) ;
for( i = 0 ; i < n ; i ++ ){
l[i] = ProjectEntrance() ;
ReverseList(l[i]) ; //逆置链表得到题目要求顺序
}
for( i = 0;i < n ; i ++) {
ShowList(l[i]) ;
for(j = 0; j < n - 1 ; j ++ ){
printf("\n") ;
}
}
return 0 ;
}
习题二:
- 问题描述
设线性表A=(a1, a2,…,am),B=(b1, b2,…,bn),试写一个按下列规则合并A、B为线性表C的算法,使得:
C= (a1, b1,…,am, bm, bm+1, …,bn) 当m≤n时;
C= (a1, b1,…,an, bn, an+1, …,am) 当m>n时。
线性表A、B、C均以单链表作为存储结构,且C表利用A表和B表中的结点空间构成。 - 输入格式
输入的第一行表示测试数据的组数T
后面跟着T组输入
每组测试数据占三行。
测试数据的第一行有两个正整数,分别为链表A和B的长度lenA,lenB(1 <= lenA, lenB <= 1000)。链表内的元素为ai,bj (-10000<= ai, bj <=10000)。
测试数据的后两行分别是链表A和B。
3. 输出格式
返回链表A和B按照上述要求处理后形成的链表C的遍历结果,,链表C长度为lenC(lenC = lenA + lenB)。输出时链表C每个元素之间用空格进行分割,并且最后要换行!
3. 备注
1、使用原表A和B的节点空间存放C。
2、写清楚注释,让审核人能理解你的思路(代码通过并且有详细的注释这题才会给满分)。
3、必须按照题目要求使用链表进行处理,不得使用数组来获取数据与获取结果!
输入样例
2
3 4
1 2 3
1 2 3 4
5 2
1 1 1 1 1
2 2
输出样例
1 1 2 2 3 3 4
1 2 1 2 1 1 1
代码实例。
#include <stdio.h>
#include <stdlib.h>
#define MAXINT 100
typedef struct Node {
int data ;
struct Node* next ;
}Node;
typedef struct Node* LinkList ;
//打印一个单链表
void ShowList(LinkList l) {
LinkList p ;
p = (LinkList)malloc(sizeof(Node));
p = l->next ;
while(p != NULL){
printf("%d ", p->data) ;
p = p->next ;
}
}
//创建一个单链表
LinkList CreatLinkList(int n) {
Node *h, *p, *q ; //设置三个结点,h保存la的头节点,q一直指向la的尾结点,p存储输入数据;
h = (LinkList)malloc(sizeof(Node));
h->next = NULL ; //初始化链表 ,让它成为一个空表
q = h ; //开始时la的头结点与尾结点重合
int i ;
for (i = 0; i < n; i ++) {
p = (LinkList)malloc(sizeof(Node)) ;
scanf("%d", &p->data) ;
p->next = q->next ;
q->next = p ;
q = p ;
}
return h ;
}
//按照要求顺序并置两个链表
LinkList MergeList(LinkList la, LinkList lb) {
LinkList pa, pb, qa, qb;
pa = la->next; //pa和pb分别指向la和lb的第一个数据结点
pb = lb->next;
LinkList pc = la;//以La的头结点为并置的头结点
while(pa && pb){
//完成pc指向la存储的元素过程
qa = pa->next; //存储pa下一个结点的数据
pa->next = NULL; //将pa指针直接指向la的末尾,相当于将pa->data这个元素从队列中分离出来
pc->next = pa; //pc是一个准备摘取数据的指针,将已经摘取出的元素放在自己的链表里
pc = pc->next;
pa = qa; //pa指针后移一个位置
//完成 pc指向lb存储的元素过程
qb = pb->next ;
pb->next = NULL;
pc->next = pb ;
pc = pc->next ;
pb = qb ;
}
pc->next = pa ? pa : pb;//最后进行判断,合并剩下的没遍历完的部分
return la;
}
LinkList ProjectEntrance() {
int n1, n2 ;
scanf("%d %d", &n1, &n2) ;
LinkList la ;
LinkList lb ;
la = CreatLinkList(n1) ; //创建链表并输入数据
lb = CreatLinkList(n2) ;
LinkList lc ;
lc = MergeList(la, lb) ; //按照原有顺序并置两个列表
return lc ;
}
int main() {
LinkList l[MAXINT] ;
int i, j, n ;
scanf("%d", &n) ;
for( i = 0 ; i < n ; i ++ ){
l[i] = ProjectEntrance() ;
}
for( i = 0;i < n ; i ++) {
ShowList(l[i]) ;
for(j = 0; j < n - 1 ; j ++ ){
printf("\n") ;
}
}
return 0 ;
}