【大一下oj作业】实验11_11_链表匹配

哇…这题真的是好坑,怎么改都是90分…感谢助教的提示,要不然真的耗不出来……

题目:
在这里插入图片描述

原来自己的做法是从上一次匹配失败的地方直接重新开始匹配,感觉没有什么问题…结果漏了很难想到的一种情况(当然只是我自己难想到而已),如果是输入:
abbcabbcabbb
abbcabbb
那么按照原来的做法,将在A列的第二个c处暂停匹配,并从c的下一个字母a进行匹配,将无法得到正确答案;而实际上B是A的子列。

原来的做法

#include<stdio.h>
#include<stdlib.h>
typedef struct node{
	int num;
	struct node* nextPtr;
}NODE;

NODE* createList(NODE*);
int function(NODE*, NODE*);
void outputResult(int);
void freeList(NODE*);

int main()
{
	NODE *headPtrA = NULL, *headPtrB = NULL;
	int state;
	headPtrA = createList(headPtrA);
	headPtrB = createList(headPtrB);
	outputResult(function(headPtrA, headPtrB));
	freeList(headPtrA);
	freeList(headPtrB);
}

NODE* createList(NODE* headPtr)
{
	int num;
	NODE* currentPtr = NULL, *lastPtr = NULL;
	scanf("%d", &num);
	while(num != -1)
	{
		currentPtr = (NODE*) malloc(sizeof(NODE));
		if(currentPtr)
		{
			currentPtr->num = num;
			if(headPtr)
			{
				lastPtr->nextPtr = currentPtr;
				lastPtr = currentPtr;
			}
			else
			{
				headPtr = currentPtr;
				lastPtr = headPtr;
			}
		}
		scanf("%d", &num);
	}
	lastPtr->nextPtr = NULL;
	return headPtr;
}

int function(NODE *headPtrA, NODE *headPtrB)
{
	int state = 0;
	NODE *tempA = headPtrA, *tempB = headPtrB;
	while(tempB && tempA)
	{
		if(tempA->num != tempB->num)
		{
			if(state)
			{
				state = 0;
				tempB = headPtrB;
			}			
		}
		else
		{
			state = 1;
			tempB = tempB->nextPtr;
		}
		//出错的地方就是这里,直接从A列不匹配的字母的下一项继续匹配		
		tempA = tempA->nextPtr;
		if(tempB != NULL && tempA == NULL)
			state = 0;
	}
	return state;
}

void outputResult(int num)
{
	switch(num)
	{
		case 1:
			printf("ListB is the sub sequence of ListA.");
			break;
		case 0:
			printf("ListB is not the sub sequence of ListA.");
			break;
	}
}

void freeList(NODE* ptr)
{
	NODE *temp = ptr;
	while(ptr)
	{
		temp = ptr->nextPtr;
		free(ptr);
		ptr = temp;
	}
}

修改后的代码

#include<stdio.h>
#include<stdlib.h>
typedef struct node{
	int num;
	struct node* nextPtr;
}NODE;

NODE* createList(NODE*);
int function(NODE*, NODE*);
void outputResult(int);
void freeList(NODE*);

int main()
{
	NODE *headPtrA = NULL, *headPtrB = NULL;
	int state;
	headPtrA = createList(headPtrA);
	headPtrB = createList(headPtrB);
	outputResult(function(headPtrA, headPtrB));
	freeList(headPtrA);
	freeList(headPtrB);
}

NODE* createList(NODE* headPtr)
{
	int num;
	NODE* currentPtr = NULL, *lastPtr = NULL;
	scanf("%d", &num);
	while(num != -1)
	{
		currentPtr = (NODE*) malloc(sizeof(NODE));
		if(currentPtr)
		{
			currentPtr->num = num;
			if(headPtr)
			{
				lastPtr->nextPtr = currentPtr;
				lastPtr = currentPtr;
			}
			else
			{
				headPtr = currentPtr;
				lastPtr = headPtr;
			}
		}
		scanf("%d", &num);
	}
	lastPtr->nextPtr = NULL;
	return headPtr;
}

int function(NODE *headPtrA, NODE *headPtrB)
{
	int state = 0;
	//多申请了一个变量temp
	NODE *tempA = headPtrA, *tempB = headPtrB, *temp = NULL;
	//相当于套了两个循环,一个大循环,记录A列开始匹配的位置;一个小循环,确定之后是否同样匹配。
	while(tempA && tempB && state == 0)
	{
		temp = tempA;
		//这里有点绕
		//如果是两值相等,则进入循环。否则大循环里A列开始匹配的位置往后。
		if(temp->num == tempB->num)
		{
			state = 1;
			//退出while循环的几种情况
			//一是B匹配完了,为NULL,确实都匹配。此时可能A的位置不是NULL,也可能是NULL
			//二是A匹配完了,为NULL,而B还没匹配完,不是NULL,此时肯定要将状态改为0.
			//三是遇到了在双方都不为空的情况下,值不相等。状态改为0.
			while(state && temp && tempB)
			{
				temp = temp->nextPtr;
				tempB = tempB->nextPtr;
				//tempB直接指向它的下一个指针时,可能会是NULL,所以不能直接temp->num != tempB->num,得分情况出来它不是空的
				if(temp && tempB)//如果两指针不为空,检查他们的值是否相等
				{
					if(temp->num != tempB->num)
					{
						state = 0; 
						tempB = headPtrB;
					}
				}
				else if(temp == NULL && tempB)
				{
					state = 0; 
					tempB = headPtrB;
				}
				//除此之外的情况是,B的指针为空了,是合理的
			}
		}
		tempA = tempA->nextPtr;
	}
	return state;
}

void outputResult(int num)
{
	switch(num)
	{
		case 1:
			printf("ListB is the sub sequence of ListA.");
			break;
		case 0:
			printf("ListB is not the sub sequence of ListA.");
			break;
	}
}

void freeList(NODE* ptr)
{
	NODE *temp = ptr;
	while(ptr)
	{
		temp = ptr->nextPtr;
		free(ptr);
		ptr = temp;
	}
}

睡了睡了……道阻且长……

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值