考研数据结构之线性表(1.7)——练习题之分离单链表的奇数偶数(C表示)

题目

设计一个算法,将一个头结点为A的单链表(其数据域为整数)分解成两个单链表A和B.使得A链表只含有原来链表中data 域为奇数的结点,而B链表只含有原链表中data城为偶数的结点,且保持原来的相对顺序。

分析

解决思路为:用指针p从头至尾扫描A链表,当发现结点data域为偶数的结点则取下,插入链表B中。因为题目要求保持原来数据元素的相对顺序,所以要用尾插法来建立B链表。

核心代码如下:

/* 将A链表中的奇数和偶数分离出来,奇数继续保留在A链表中,偶数保留在B链表中 */
/* *A指的是要处理的单链表;*&B指的是要保存偶数的新链表 */
void sepEvenAndOdd(LNode *A,LNode *&B) {
	LNode *tempA=A->next;// 开始结点
	LNode *pre=A;// 保存A链表的头结点(其实是保存的是前驱结点)
	B=(LNode *)malloc(sizeof(LNode)); // 创建B链表
	B->next=NULL;
	LNode *tempB=B; // 保存B链表的头结点(其实是尾指针结点)
	LNode *tempDelNode; // 临时保存删除结点
	while(tempA!=NULL) { // 循环A链表
		if(tempA->data%2!=0) { // 判断A链表中的结点的data值是奇数还是偶数
			pre=tempA;// 如果是奇数,将前驱结点置为当前结点
			tempA=tempA->next; // 并且到下一个结点去
		} else { // 如果是偶数
			tempDelNode=tempA;// 临时保存要删除的结点,即偶数结点
			pre->next=tempDelNode->next;// 连接A链表,删除偶数结点
			tempA=tempA->next; // A链表继续遍历到下一个结点
			tempB->next=tempDelNode; // 将偶数结点链接到B链表上
			tempB=tempDelNode;// 将B链表的尾结点置为当前新添加的结点
		}
	}
	tempB->next=NULL;// 注意:需将添加结点成功的B链表终端节点的next置为NULL
}

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
// 声明单链表结构体
struct LNode {
	int data;
	struct LNode *next;
};

/* 通过用户输入数据创建一个单链表,由用户输入整型测试数据 */
/* 返回一个单链表 */
LNode * createList() {
	LNode *head;
	LNode *p1,*p2;
	p1=p2=(LNode *)malloc(sizeof(LNode));
	head=(LNode *)malloc(sizeof(LNode));
	scanf("%ld",&p1->data);
	int i=0;
	while(p1->data!=0) { // 当用户在控制台输入0时结束循环
		i+=1;
		if(i==1) {
			head->next=p1;
		} else {
			p2->next=p1;
		}
		p2=p1;
		p1=(LNode *)malloc(sizeof(LNode));
		scanf("%ld",&p1->data);
	}
	p2->next=NULL;
	return head;
}

/* 打印单链表 */
/* *list指的是要被打印输出的单链表 */
void printList(LNode *list) {
	LNode *temp=list->next;// 单链表的开始结点
	printf("\n");
	while(temp!=NULL) { // 循环单链表
		printf("%ld\t",temp->data); // 打印单链表中的data数据
		temp=temp->next; // 遍历至下一个结点
	}
	printf("\n"); // 换行
}

/* 将A链表中的奇数和偶数分离出来,奇数继续保留在A链表中,偶数保留在B链表中 */
/* *A指的是要处理的单链表;*&B指的是要保存偶数的新链表 */
void sepEvenAndOdd(LNode *A,LNode *&B) {
	LNode *tempA=A->next;// 开始结点
	LNode *pre=A;// 保存A链表的头结点(其实是保存的是前驱结点)
	B=(LNode *)malloc(sizeof(LNode)); // 创建B链表
	B->next=NULL;
	LNode *tempB=B; // 保存B链表的头结点(其实是尾指针结点)
	LNode *tempDelNode; // 临时保存删除结点
	while(tempA!=NULL) { // 循环A链表
		if(tempA->data%2!=0) { // 判断A链表中的结点的data值是奇数还是偶数
			pre=tempA;// 如果是奇数,将前驱结点置为当前结点
			tempA=tempA->next; // 并且到下一个结点去
		} else { // 如果是偶数
			tempDelNode=tempA;// 临时保存要删除的结点,即偶数结点
			pre->next=tempDelNode->next;// 连接A链表,删除偶数结点
			tempA=tempA->next; // A链表继续遍历到下一个结点
			tempB->next=tempDelNode; // 将偶数结点链接到B链表上
			tempB=tempDelNode;// 将B链表的尾结点置为当前新添加的结点
		}
	}
	tempB->next=NULL;// 注意:需将添加结点成功的B链表终端节点的next置为NULL
}

int main() {
	/* [0.]创建初始测试单链表 */
	LNode *list,*list2;
	list=createList();// 创建测试链表
	list2=list;
	printList(list);// 打印单链表

	sepEvenAndOdd(list,list2);// 分离奇数偶数链表
	printList(list); // 打印奇数链表
	printList(list2);// 打印偶数链表

	return 0;
}

运行结果如下:

扩展

下面是关于求一个链表中奇数和偶数的。

分离链表中的奇数留下偶数:

/* 分离奇数结点,得到全是偶数结点的链表 */ 
void sepOdd(LNode *A){
	LNode *temp=A->next;// 开始结点
	LNode *pre=A;// 头结点(直接前驱)
	LNode *tempDelNode;// 临时保存被删除结点
	while(temp!=NULL){
		if(temp->data%2==0){
			pre=temp;
			temp=temp->next;
		}else{
			tempDelNode=temp;
			pre->next=tempDelNode->next;
			temp=temp->next;
			free(tempDelNode);
		}
	} 
	 
}

分离链表中的偶数留下奇数:

/* 分离偶数结点,得到全是奇数结点的链表 */ 
void sepEven(LNode *A){
	LNode *temp=A->next;// 开始结点
	LNode *pre=A;// 直接前驱 
	LNode *tempDelNode;
	while(temp!=NULL){
		if(temp->data%2!=0){
			pre=temp;
			temp=temp->next;
		}else{
			tempDelNode=temp;
			pre->next=tempDelNode->next;
			temp=temp->next;
			free(tempDelNode);
		}
	} 
}

测试代码如下:

#include <stdio.h>
#include <stdlib.h>
// 声明单链表结构体
struct LNode {
	int data;
	struct LNode *next;
};

/* 通过用户输入数据创建一个单链表,由用户输入整型测试数据 */
/* 返回一个单链表 */
LNode * createList() {
	LNode *head;
	LNode *p1,*p2;
	p1=p2=(LNode *)malloc(sizeof(LNode));
	head=(LNode *)malloc(sizeof(LNode));
	scanf("%ld",&p1->data);
	int i=0;
	while(p1->data!=0) { // 当用户在控制台输入0时结束循环
		i+=1;
		if(i==1) {
			head->next=p1;
		} else {
			p2->next=p1;
		}
		p2=p1;
		p1=(LNode *)malloc(sizeof(LNode));
		scanf("%ld",&p1->data);
	}
	p2->next=NULL;
	return head;
}

/* 打印单链表 */
/* *list指的是要被打印输出的单链表 */
void printList(LNode *list) {
	LNode *temp=list->next;// 单链表的开始结点
	printf("\n");
	while(temp!=NULL) { // 循环单链表
		printf("%ld\t",temp->data); // 打印单链表中的data数据
		temp=temp->next; // 遍历至下一个结点
	}
	printf("\n"); // 换行
}

/* 分离偶数结点,得到全是奇数结点的链表 */ 
void sepEven(LNode *A){
	LNode *temp=A->next;// 开始结点
	LNode *pre=A;// 直接前驱 
	LNode *tempDelNode;
	while(temp!=NULL){
		if(temp->data%2!=0){
			pre=temp;
			temp=temp->next;
		}else{
			tempDelNode=temp;
			pre->next=tempDelNode->next;
			temp=temp->next;
			free(tempDelNode);
		}
	} 
}

/* 分离奇数结点,得到全是偶数结点的链表 */ 
void sepOdd(LNode *A){
	LNode *temp=A->next;// 开始结点
	LNode *pre=A;// 头结点(直接前驱)
	LNode *tempDelNode;// 临时保存被删除结点
	while(temp!=NULL){
		if(temp->data%2==0){
			pre=temp;
			temp=temp->next;
		}else{
			tempDelNode=temp;
			pre->next=tempDelNode->next;
			temp=temp->next;
			free(tempDelNode);
		}
	} 
	 
}

int main() {
	/* [0.]创建初始测试单链表 */
	LNode *list,*list2;
	
	list=createList();// 创建测试链表
	printList(list);// 打印单链表
	sepEven(list);// 分离偶数 
	printList(list);// 打印全是奇数的链表  
	
	list2=createList();
	printList(list2);
	sepOdd(list2);// 分离奇数 
	printList(list2);// 打印全是偶数的链表 

	return 0;
}

结果如下:

分离顺序表的奇数和偶数

分离的核心代码如下:

/* 分离奇数,留下全是偶数的顺序表 */ 
/* &list指的是要被分离的顺序表 */ 
void sepOdd(SqlList &list){
	int i=0;// 计数器,记录当前是第几个数 
	while(i<list.length){
		if(list.a[i]%2!=0){ // 判断是否是偶数
			// 如果不是偶数则删除顺序表中的奇数 
			for(int m=i;m<list.length-1;m++){ // 将奇数后的所有数向前移动一个位置 
				list.a[m]=list.a[m+1];
			}
			list.length--;// 顺序表长度减1 
		}else{// 如果是奇数的话,则保留在顺序表中,继续判断下一个数 
			i++;// 计数器+1 
		}
	}
}

/* 分离偶数,留下全是奇数的顺序表 */ 
/* &list指的是要被分离的顺序表 */ 
void sepEven(SqlList &list){
	int i=0;// 计数器
	while(i<list.length){
		if(list.a[i]%2==0){
			for(int m=i;m<list.length-1;m++){
				list.a[m]=list.a[m+1];
			}
			list.length--;
		}else{
			i++;
		}
	} 
} 
 

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
 
#define maxSize 20
 
typedef struct SqlList {
	int a[maxSize];
	int length;
} SqlList;
 
/* 创建顺序表 */ 
void createList(SqlList &L) {
	int tempNo = 1;
	int tempData = 0;
	do {
		printf("请输入顺序表第%d个元素:",tempNo);
		scanf("%d",&tempData);
		if(tempData!=-1) {
			L.a[tempNo-1] = tempData;
			L.length = tempNo;
			tempNo++;
		}
	} while(tempNo<=maxSize&&tempData!=-1);
}
 
/* 打印顺序表 */ 
void printSqlList(SqlList list) {
	printf("\n");
	for(int i=0; i<list.length; i++) {
		printf("%d\t",list.a[i]);
	}
	printf("\n");
}

/* 分离奇数,留下全是偶数的顺序表 */ 
/* &list指的是要被分离的顺序表 */ 
void sepOdd(SqlList &list){
	int i=0;// 计数器,记录当前是第几个数 
	while(i<list.length){
		if(list.a[i]%2!=0){ // 判断是否是偶数
			// 如果不是偶数则删除顺序表中的奇数 
			for(int m=i;m<list.length-1;m++){ // 将奇数后的所有数向前移动一个位置 
				list.a[m]=list.a[m+1];
			}
			list.length--;// 顺序表长度减1 
		}else{// 如果是奇数的话,则保留在顺序表中,继续判断下一个数 
			i++;// 计数器+1 
		}
	}
}

/* 分离偶数,留下全是奇数的顺序表 */ 
/* &list指的是要被分离的顺序表 */ 
void sepEven(SqlList &list){
	int i=0;// 计数器
	while(i<list.length){
		if(list.a[i]%2==0){
			for(int m=i;m<list.length-1;m++){
				list.a[m]=list.a[m+1];
			}
			list.length--;
		}else{
			i++;
		}
	} 
} 
 
int main() {
	SqlList list,list2;// 声明一个顺序表
	
	createList(list); // 创建顺序表 
	printSqlList(list);// 打印创建成功的顺序表 
	sepOdd(list);// 分离奇数留下偶数列表 
	printSqlList(list);// 打印偶数顺序表 
	
	createList(list2); // 创建顺序表 
	printSqlList(list2);// 打印创建成功的顺序表 
	sepEven(list2);// 分离偶数留下奇数列表 
	printSqlList(list2);// 打印奇数顺序表 
 
	return 0;
}

结果如下:

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值