这是一个面试问题,我想我会和你们其他人分享。
如何在不使用“if”的情况下有效地添加到链表的尾部?
从此功能中删除if。 (?
仍为if
)。
typedef struct tNode_ tNode;
struct tNode_ {
tNode* pNext;
int data;
};
tNode* pHead = NULL;
tNode* pTail = NULL;
AddTail(tNode* pNode){
if(!pTail) {
pHead = pNode;
}
else {
pTail->pNext = pNode;
}
pTail = pNode;
pTail->pNext = NULL;
}
答案 0 :(得分:2)
执行此操作的一种方法(使用愚蠢的方法)是使用短路逻辑运算符&&
和||
的行为。例如,您可以这样做:
AddTail(tNode* pNode){
pTail || (pHead = pNode);
!pTail || (pTail->pNext = pNode);
pTail = pNode;
pTail->pNext = NULL;
}
这是有效的,因为如果ptail
为null,则第一个语句的第一部分将计算为false,从而强制评估||
语句的后半部分。如果它是非null,则不会评估语句的后半部分。类似的逻辑适用于下一个陈述。
那就是说,这是一个非常愚蠢的面试问题,老实说,我不知道他们会得到什么。就个人而言,我会质疑某人试图评估你编写这样代码的能力的智慧。
希望这有帮助!
答案 1 :(得分:1)
typedef struct tNode_ tNode;
struct tNode_ {
tNode* pNext;
int data;
};
/* normal initialization for pHead */
tNode* pHead = NULL;
/* the trick is to point at where you want the next pointer to go
* instead of saving a pointer to the node.
*/
tNode** ppTail = &pHead;
AddTail(tNode* pNode){
pNode->pNext = NULL;
/* update the next pointer */
*ppTail = pNode;
/* save the address of the next pointer */
ppTail = &pNode->pNext;
}
main(){
int cnt;
tNode* pNew;
for(cnt=0; cnt<10; cnt++){
pNew = malloc(sizeof(tNode));
pNew->data = cnt;
AddTail(pNew);
}
for(pNew = pHead; pNew; pNew = pNew->pNext){
printf("%d\n", pNew->data);
}
}
答案 2 :(得分:1)
我会为每个列表使用一个虚拟元素(或称为sentinel node)。附加到头部会附加到虚拟对象,附加到尾部只是附加到最后一个元素,然后根据定义存在。
typedef struct tNode_ tNode;
struct tNode_ {
tNode* pNext;
int data;
};
// The Remove operation must never remove this dummy!
tNode* pDummy = (tNode*)calloc(1, sizeof(tNode));
tNode* pHead = pDummy;
tNode* pTail = pDummy;
AddTail(tNode* pNode){
pTail->pNext = pNode;
pTail = pNode;
pTail->pNext = NULL;
}
答案 3 :(得分:1)
tNode pHead;
tNode pTail;
void init() {
pHead.pNext = &pTail;
pTail.pNext = &pHead;
}
AddTail(tNode* pNode){
pTail.pNext->pNext = pNode;
pNode->pNext = &pHead;
pTail.pNext = pNode;
}