数据结构练习(3)

习题1:

已知两个链表A和B分别表示两个集合,其元素递增排列。请设计一个算法,求出A与B的交集,并将结果存放在A链表中。

【分析】当看到这道题目时,我们一般会想到对两个链表进行遍历,将每个链表的元素依次比较,最后将相同的元素存放在A链表中。但是,若A链表中有n个元素,B链表中有n个元素,这种算法的时间复杂度为O(n^2)。时间复杂度过高,并且,此时我们忽略了题目中的已知条件(元素递增排列)。

        现在,我们使用“元素递增排列”这一个关键的要素,可以分析出,一旦A链表中指针正在指向元素小于B链表中指针正在指向的元素,则A链表中的这个元素不可能再与B元素中该指针指向的元素及其后链接的元素相等。

 

 

 顺次比较,得到目标链表。

SLTNode* SLTIntersect(SLTNode** list1,SLTNode** list2){
//cur1依次指向链表A的每一个节点,cur2依次指向链表B的每一个节点
	SLTNode *cur1=*list1, *cur2=*list2;
//dst_head 是目标链表的头节点(便于返回)
//dst_tail是目标链表的尾节点(便于尾插交集元素的节点)
	SLTNode *dst_head=NULL,*dst_tail=NULL;
//当链表A或者链表B中的任意一个链表被遍历结束,循环结束
	while(cur1&&cur2){

//链表A中的元素小于链表B中的元素,删除链表A中的该节点
		if(cur1->data<cur2->data)
		{
			SLTNode* tmp=cur1;
			cur1=cur1->next;
			free(tmp);
		}
//链表B中的元素小于链表A中的元素,删除链表B中的该节点
		else if(cur2->data<cur1->data){
			SLTNode* tmp=cur2;
			cur2=cur2->next;
			free(tmp);
		}
//链表A中的元素等于链表B中的元素,将该节点尾插到目标链表
		else if (cur1->data==cur2->data){
            //若目标链表为空
			if(dst_head==NULL){
				dst_head=dst_tail=cur1;
			}
            //若目标链表不为空
			else{
				dst_tail->next=cur1;
				dst_tail=dst_tail->next;
		}	
            //删除链表A中的该节点
			SLTNode* tmp1=cur1;
			cur1=cur1->next;
			free(tmp1);
			
            //删除链表B的该节点
			SLTNode* tmp2=cur2;
			cur2=cur2->next;
			free(tmp2);
		}
	}
//若链表A未被遍历完,释放A中的所有节点
	while(cur1){
		SLTNode* tmp=cur1;
		cur1=cur1->next;
		free(tmp);
	}
//若链表B未被遍历完,释放B中的所有节点
	while(cur2){
		SLTNode* tmp=cur2;
		cur2=cur2->next;
		free(tmp);
	}
//为目标链表结尾
	dst_tail->next=NULL;
//将目标函数的头节点赋给链表A的头节点
	*list1=dst_head;
	return *list1;
}

进行测试:(使用Dev C++)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode {
	SLTDataType data;
	struct SListNode* next;
}SLTNode;
void SLTPrint(SLTNode* phead) {
	SLTNode* cur = phead;
	while (cur) {
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
SLTNode* BuySLTNode(SLTDataType x) {
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL) {
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void SLTPushBack(SLTNode** pphead, SLTDataType x) {
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	if (*pphead == NULL) {
		*pphead = newnode;
	}
	else {
		//找尾
		SLTNode* tail = *pphead;
		while (tail->next != NULL) {
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
SLTNode* SLTIntersect(SLTNode** list1,SLTNode** list2){
	SLTNode *cur1=*list1, *cur2=*list2;
	SLTNode *dst_head=NULL,*dst_tail=NULL;
	while(cur1&&cur2){
		if(cur1->data<cur2->data)
		{
			SLTNode* tmp=cur1;
			cur1=cur1->next;
			free(tmp);
		}
		else if(cur2->data<cur1->data){
			SLTNode* tmp=cur2;
			cur2=cur2->next;
			free(tmp);
		}
		else if (cur1->data==cur2->data){
			if(dst_head==NULL){
				dst_head=dst_tail=cur1;
			}
			else{
				dst_tail->next=cur1;
				dst_tail=dst_tail->next;
		}	
			SLTNode* tmp1=cur1;
			cur1=cur1->next;
			free(tmp1);
			
			SLTNode* tmp2=cur2;
			cur2=cur2->next;
			free(tmp2);
		}
	}
	while(cur1){
		SLTNode* tmp=cur1;
		cur1=cur1->next;
		free(tmp);
	}
	while(cur2){
		SLTNode* tmp=cur2;
		cur2=cur2->next;
		free(tmp);
	}
	dst_tail->next=NULL;
	*list1=dst_head;
	return *list1;
}


int main() {
	SLTNode* list1 = NULL;
	SLTPushBack(&list1, 1);
	SLTPushBack(&list1, 3);
	SLTPushBack(&list1, 4);
	SLTPushBack(&list1, 5);
	SLTPushBack(&list1, 8);
	SLTNode* list2=NULL;
	SLTPushBack(&list2, 3);
	SLTPushBack(&list2, 4);
	SLTPushBack(&list2, 4);
	SLTPushBack(&list2, 6);
	SLTPrint(list1);
	SLTPrint(list2);
	SLTIntersect(&list1,&list2);
	SLTPrint(list1);
	return 0;
}

运行结果:

 习题2:

设计算法将一个带头节点的单链表分解为两个具有同样结构的链表B和C,其中B表的节点为A表中值小于0的节点,C表的节点为A表中值大于0 的节点(链表A中的元素为非零整数,要求B、C表利用A表的节点)。

【分析】对A中的节点依次进行比较,若小于0则将节点尾插到B表中,若大于0则将节点尾插到A表中。

void  SLTPartiton(SLTNode* phead) {
	SLTNode* lGuard = BuySLTNode(0);
	SLTNode* lTail = lGuard;
	SLTNode* gGuard = BuySLTNode(0);
	SLTNode* gTail = gGuard;
	gTail->next = lTail->next = NULL;
	SLTNode* cur = phead;
	while (cur) {
		if (cur->data < 0)
		{
			lTail->next = cur;
			lTail = lTail->next;
		}
		else {
			gTail->next = cur;
			gTail = gTail->next;
		}
		cur = cur->next;
	}
	lTail->next = NULL;
	gTail->next = NULL;
	SLTPrint(lGuard->next);
	SLTPrint(gGuard->next);
}

 运行测试:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode {
	SLTDataType data;
	struct SListNode* next;
}SLTNode;
void SLTPrint(SLTNode* phead) {
	SLTNode* cur = phead;
	printf("head->");
	while (cur) {
		printf("(%d)->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
SLTNode* BuySLTNode(SLTDataType x) {
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL) {
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void SLTPushBack(SLTNode** pphead, SLTDataType x) {
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	if (*pphead == NULL) {
		*pphead = newnode;
	}
	else {
		//找尾
		SLTNode* tail = *pphead;
		while (tail->next != NULL) {
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
void  SLTPartiton(SLTNode* phead) {
	SLTNode* lGuard = BuySLTNode(0);
	SLTNode* lTail = lGuard;
	SLTNode* gGuard = BuySLTNode(0);
	SLTNode* gTail = gGuard;
	gTail->next = lTail->next = NULL;
	SLTNode* cur = phead;
	while (cur) {
		if (cur->data < 0)
		{
			lTail->next = cur;
			lTail = lTail->next;
		}
		else {
			gTail->next = cur;
			gTail = gTail->next;
		}
		cur = cur->next;
	}
	lTail->next = NULL;
	gTail->next = NULL;
	SLTPrint(lGuard->next);
	SLTPrint(gGuard->next);
}


int main() {
	SLTNode* list1 = BuySLTNode(0);
	SLTPushBack(&list1, 1);
	SLTPushBack(&list1, 9);
	SLTPushBack(&list1, -4);
	SLTPushBack(&list1, 5);
	SLTPushBack(&list1, -8);
	SLTPrint(list1->next);
	SLTPartiton(list1);
	return 0;
}

结果如下:

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值