面试时面试官要求手写双向链表的 删除操作,当时没有考虑到边界条件,导致被刷;
现在 列举下代码以及优化,作为事后反思:
C 版本:
双向链表的结构定义
typedefstruct doubleLink { int data; struct doubleLink *prior; struct doubleLink *suffix; }DOUBLE_LINK;
创建一个双向链表
/*创建一个双链表*/ DOUBLE_LINK *createDoubleLink() { DOUBLE_LINK *head = NULL; head =(DOUBLE_LINK*)malloc(sizeof*head); head->prior = NULL; head->suffix = NULL; return head; }
插入函数
/*插入节点*/ bool insertNode(DOUBLE_LINK*head,int data) { if(head == NULL) returnfalse; DOUBLE_LINK *currNodep = NULL; DOUBLE_LINK *nextp = NULL; DOUBLE_LINK *newNodep = NULL; for(currNodep = head;(nextp = currNodep->suffix)!= NULL; currNodep = nextp) { if(nextp->data == data) returnfalse; if(nextp->data > data) break; } newNodep =(DOUBLE_LINK*)malloc(sizeof*newNodep); if(newNodep == NULL) returnfalse; newNodep->data = data; #if 1 /*需要插入双向链表时,遍历到需要插入的位置,开始对待插入的节点,前驱指针和后驱指针赋值, 后驱指针固定指向下一个节点指针,前驱需要区分 前指针是否是 头节点。 再对 当前节点的前驱指针赋值,需要区分待插入的点是不是 尾节点*/ //1.当前节点的后驱指针 currNodep->suffix = newNodep; //2.新节点的前驱指针 if(currNodep == head) newNodep->prior = NULL; else newNodep->prior = currNodep; //3.新节点的后驱指针 newNodep->suffix = nextp; //4.下一个节点的前驱指针 if(nextp == NULL)//到了尾节点处,则将头节点的前驱指向该尾节点,这是双向链表的结构精髓所在 head->prior = newNodep; else nextp->prior = newNodep; #else if(nextp != NULL) { //one not in the tail newNodep->suffix = nextp; currNodep->suffix = newNodep; if(currNodep != head)// not the head { newNodep->prior = currNodep; } else// currnode is head { newNodep->prior = NULL; } nextp->prior = newNodep; } else { //in the tail currNodep->suffix = newNodep; if(currNodep != head)//not the head { newNodep->prior = currNodep; } else//is the head { head->prior = newNodep; newNodep->prior = NULL; } newNodep->suffix = NULL; } #endif returntrue; }
删除某个节点
/*删除某个节点*/ bool deleteNode(DOUBLE_LINK *head, DOUBLE_LINK *item) { _ASSERT(head != NULL); _ASSERT(item != NULL); DOUBLE_LINK *currentNodep = NULL; DOUBLE_LINK *nextp = NULL; for(currentNodep = head;(nextp = currentNodep->suffix)!= NULL; currentNodep = nextp) { if(nextp == item) { /*当前节点为头结点时,这一点很重要*/ if(currentNodep == head)// the head { currentNodep->prior = NULL; currentNodep->suffix = nextp->suffix; free(nextp); nextp = NULL; break; } //最后一个节点时 elseif(nextp->suffix == NULL)// the tail { currentNodep->suffix = NULL; free(nextp); nextp = NULL; break; } else// the mid { DOUBLE_LINK *tmp = nextp->suffix; currentNodep->suffix = nextp->suffix; nextp->prior = currentNodep; free(nextp); nextp = tmp; } } } returntrue; }
删除节点函数优化
bool deleteNode_opt(DOUBLE_LINK *head, DOUBLE_LINK *item) { _ASSERT(head != NULL); _ASSERT(item != NULL); //要删除第一个节点 if(item == head->suffix) { head->suffix = item->suffix; item->suffix->prior = NULL; } //要删除最后一个节点 elseif(item == head->prior) { head->prior = item->prior; item->prior->suffix = NULL; } else { item->prior->suffix = item->suffix; item->suffix->prior = item->prior; } free(item); item = NULL; returntrue; }
打印函数
void printAllNode(DOUBLE_LINK *head) { _ASSERT(head != NULL); DOUBLE_LINK *currentNodep = NULL; DOUBLE_LINK *nextNodep = NULL; std::cout <<"Node data is: "; for(currentNodep = head;(nextNodep = currentNodep->suffix)!= NULL; currentNodep = nextNodep) { std::cout << nextNodep->data<<" "; } std::cout << std::endl; }