[作业]【C语言实现】假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,并要求利用原表结点。

习题一:

  1. 问题描述
    假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,并要求利用原表(即A表和B表的)结点空间存放表C。
  2. 输入格式
    输入的第一行表示测试数据的组数T
    后面跟着T组输入
    每组测试数据占三行
  3. 输出格式
    返回链表A和B按照上述要求处理后形成的链表C的遍历结果,链表C按元素值递减有序排列,长度为lenC(lenC = lenA + lenB)。输出时链表C每个元素之间用空格进行分割,并且最后要换行!
  4. 备注
    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 ;
}

习题二:

  1. 问题描述
    设线性表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表中的结点空间构成。
  2. 输入格式
    输入的第一行表示测试数据的组数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 ;
}

  • 10
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一: 内容:1、设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。试设计一算法,将x插入到线性表的适当位置上,以保持线性表有序性。 2、用向量存储结构,试设计一个算法,仅用一个辅助结点实现线性表中的结点循环右移k位的运算。 3、用向量存储结构,试设计一个算法,仅用一个辅助结点实现线性表逆置的运算。 要求:了解线性表的逻辑结构特征,熟练掌握线性表的顺序存储结构的描述方法,及在其上实现各种基本运算的方法。 二:内容:1、已知带头结点的动态单链表L中的结点是按整数递增排序的,试写一算法为x的结点插入到L中,使L仍然有序。 2、设计一算法,逆置带头结点的动态链表L。要求利用原表结点空间,并要求用尽可能少的时间完。 3、假设两个元素递增有序线性表A和B,单链表存储结构,试编写算法将A和B归并一个元素递减有序线性表C,并要求利用原表的空间存放C。 要求:熟练掌握线性表的单链式链接存储结构及在其上实现线性表的各种基本运算的方法。 三:内容:1、假设在长度大于1的单循环链表中,既无头结点也无头指针。s为指向某个结点的指针,试编写算法删除结点*s的直接前驱结点。 2、已知由单链表示的线性表中,含有三类字符的数据元素(如:字母、数字和其它字符),设计算法构造三个以循环链表示的线性表,使每一个中只含同一类的字符,且利用原表中的结点空间为这三个的空间。(头结点可以另辟空间) 3、有一双链表,每个结点中除有prior、data和next域外,还有一访问频度域freq,在链表被启用前,其初始化为零。每当在链表上进行一次LOCATE(L,x)运算,元素为x的结点中freq域的增1,并使此链表结点保持按freq递减的顺序排列,以便使频繁访问的结点总是靠近头。设计满足上述要求的LOCATE算法要求:熟练掌握线性表的循环链式和双链式链接存储结构及在其上实现线性表的各种基本运算的方法。 四:内容:1、设单链表中存放着n个字符,设计算法,判断该字符串中是否有中心对称关系。例如:xyzzyx、xyzyx都算是中心对称的字符串。 2、设计算法判断一个算术达式的圆括号是否配对。(提示:对达式进行扫描,遇‘(’进栈,遇‘)’退掉栈顶的‘(’,达式被扫描完毕,栈为空) 3、假设以带头结点的循环链表示队列,并只设一个指针指向队尾,编写相应的置队空、入队和出队算法要求:掌握栈和队列的数据结构的特点;熟练掌握在两种存储结构实现栈和队列的基本运算;学会利用栈和队列解决一些实际问题。 五:内容:1、若X和Y是用结点大小为1的单链表示的串,设计算法找出X中第一个不在Y中出现的字符。 2、设计一算法,在顺序串上实现串的比较运算strcmp(S,T)。 3、若S和T是用结点大小为1的单链表存储的两个串,设计算法将S中首次与T匹配的子串逆置。 要求:熟练掌握串的顺序和链接存储结构实现方法;熟练掌握在两种存储结构实现串的各种运算。 六:内容:1、以二叉链表存储结构,设计求二叉树高度的算法。 2、一棵n个结点的完全二叉树用向量存储结构,用非递归算法实现对该二叉树进行前序遍历。 3、以二叉链表存储结构编写非递归的前序、中序、后序遍历算法要求:熟悉二叉树的各种存储结构的特点及适用范围;掌握建立二叉树的存储结构的方法;熟练掌握二叉树的前序、中序、后序遍历的递归及非递归算法;灵活运用递归的遍历算法实现二叉树的其它各种运算。
要将A和B归并一个元素递减有序排列线性表C,可以按照以下步骤进行: 1. 创建一个新的链表C,并初始化为空链表。 2. 分别设置两个指针p和q,分别指向A和B的头结点。 3. 比较p和q指向结点元素大小,将较小的结点插入到链表C的头部,并更新相应指针。 4. 重复步骤3,直到其中一个链表遍历完毕。 5. 将剩余未遍历完的链表中的结点依次插入到链表C的头部。 6. 返回链表C。 下面是C语言实现的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表结点结构体 typedef struct Node { int data; struct Node* next; } Node; // 将元素插入到链表头部 void insertNode(Node** head, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = *head; *head = newNode; } // 归并两个有序链表 Node* mergeLists(Node* listA, Node* listB) { Node* head = NULL; // 归并后的链表结点 Node* p = listA; Node* q = listB; // 比较两个链表结点,将较小的结点插入到新链表头部 while (p != NULL && q != NULL) { if (p->data <= q->data) { insertNode(&head, p->data); p = p->next; } else { insertNode(&head, q->data); q = q->next; } } // 将剩余未遍历完的链表中的结点插入到新链表头部 while (p != NULL) { insertNode(&head, p->data); p = p->next; } while (q != NULL) { insertNode(&head, q->data); q = q->next; } return head; } // 打印链表 void printList(Node* head) { Node* p = head; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { // 创建链表A Node* listA = NULL; insertNode(&listA, 5); insertNode(&listA, 3); insertNode(&listA, 1); // 创建链表B Node* listB = NULL; insertNode(&listB, 6); insertNode(&listB, 4); insertNode(&listB, 2); // 归并链表A和链表B Node* listC = mergeLists(listA, listB); // 打印归并后的链表C printf("归并后的链表C:"); printList(listC); return 0; } ``` 测试用例的输出结果为: ``` 归并后的链表C:6 5 4 3 2 1 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值