这两种算法之间有很大区别吗?
这是我的:
void MergeList(sqList la,sqList lb,sqList *lc){
int j,k,n=0;
for (j = la.length - 1, k = lb.length - 1; j >= 0 && k >= 0; ){
if (*(la.elem + j) > *(lb.elem + k)){
*(lc->elem + n) = *(la.elem + j);
j--;
} else if(*(la.elem + j) < *(lb.elem + k)){
*(lc->elem + n) = *(la.elem + k);
k--;
} else {
*(lc->elem + n) = *(la.elem + j);
j--;
k--;
}
n++;
lc->length++;
}
for ( ;j >= 0; j--){
*(lc->elem + n) = *(la.elem + j);
lc->length++;
}
for ( ;k >= 0; k--){
*(lc->elem + n) = *(lb.elem + k);
lc->length++;
}
}
这是本书中的
void MergeList(sqList la,sqList lb,sqList *lc){
ElemType *pa,*pb,*pc,*pa_first,*pb_first;
pa = la.elem + la.length - 1;
pb = lb.elem + lb.length - 1;
pc = lc->elem;
pa_first = la.elem;
pb_first = lb.elem;
while(pa >= pa_first && pb >= pb_first){
if(*pa > *pb)
*pc++ = *pa--;
else if(*pa < *pb)
*pc++ = *pb--;
else{
*pc++ = *pa-- = *pb--;
}
lc->length++;
}
while(pa >= pa_first)
*pc++ = *pa--;
while(pb >= pb_first)
*pc++ = *pb--;
}
答案 0 :(得分:1)
我的重构...
所做的更改:
使MergeList
返回列表,因此调用者可以执行resultList = MergeList(...
之类的操作,以使所产生的影响更加明显。
更改了变量名,使它们更具描述性
到处都添加了“左括号前的空格”
到处都添加了“逗号后的空格”
在各处添加了“运算符周围的空间”
使用数组查找替换了指针计算(请参见Jeremy Friesner的评论)
替换了过于复杂的for()
恶作剧(使用逗号,空片断),更容易/更容易读取循环
添加了文档(功能开始之前)
在功能中添加了注释
将const
添加到了来源列表
代码:
// Construct a new list sorted by descending order of "elem" by merging data from
// two existing lists that are already sorted by descending order of "elem".
//
// WARNINGS:
// If both source lists are not sorted the resulting list will not be sorted.
// Caller MUST ensure that enough memory is allocate for the resulting list before calling this function.
sqList *MergeList(const sqList list_a, const sqList list_b, sqList *result_list) {
int j, k, n = 0;
// Do entries from both source lists until there's nothing left in at least one of the source lists
j = list_a.length - 1;
k = list_b.length - 1;
while(j >= 0 && k >= 0) {
if (list_a.elem[j] > list_b.elem[k]) {
result_list->elem[n] = list_a.elem[j];
j--;
} else if(list_a.elem[j] < list_b.elem[k]) {
result_list->elem[n] = list_a.elem[k];
k--;
} else {
result_list->elem[n] = list_a.elem[j];
j--;
k--;
}
n++;
result_list->length++;
}
// If all entries in list_a haven't been consumed, copy the remaining entries to the result list
while(j >= 0) {
result_list->elem[n] = list_a.elem[j];
result_list->length++;
j--;
}
// If all entries in list_b haven't been consumped, copy the remaining entries to the result list
while (k >= 0) {
result_list->elem[n] = list_b.elem[k];
result_list->length++;
k--;
}
return result_list;
}
答案 1 :(得分:0)
这两种算法之间有很大区别吗?
他们做的不一样,所以是的,有很大的不同
您的代码中有一个错误,我想这是一个经典的复制粘贴错误。这行是错误的:
} else if(*(la.elem + j) < *(lb.elem + k)){
*(lc->elem + n) = *(la.elem + k); // ERROR... la.elem should be lb.elem
k--;
} else {
除了lc->length
的计算不同。在本书的这段代码中:
while(pa >= pa_first)
*pc++ = *pa--;
没有增量,但是在您的代码中
for ( ;j >= 0; j--){
*(lc->elem + n) = *(la.elem + j);
lc->length++;
}
有。所以又有一个区别。我猜这本书是错的,而你是正确的。
本书中的代码递减一个指针,并将其与指向第一个元素的指针进行比较。由于递减的指针最终将指向第一个元素之前,因此代码具有未定义的行为。
我的老师告诉我我的代码是垃圾,为什么?
老师不应该这样说...。而老师至少应该解释原因。
评估代码时,有几件事要重点关注:
功能,即它在做什么吗?这是最高优先级
性能,即代码是否以您需要的速度执行
可维护性,即易于阅读,理解和维护的代码。
您的代码不易阅读,但是由于书中的代码是错误的,我仍然会更喜欢您的代码(在修正了拼写错误之后)。
您可以更改以提高可读性的一个简单示例:
*(la.elem + j) --> la.elem[j]
还要注意,这本书的代码不容易阅读。请看这本书的这一行:
*pc++ = *pa-- = *pb--;
作为代码阅读者,只能想到:“此代码应该做什么?”