哇…这题真的是好坑,怎么改都是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;
}
}
睡了睡了……道阻且长……