剑指Offer----面试题13:在O(1)时间删除链表结点
2016-06-03 18:32
861 查看
题目:
给定单向链表的头结点和一个指针结点,定义一个函数在O(1)时间删除该结点。方法一:
在以往的算法中,我们往往都是从链表的头结点开始循环遍历找到该结点的前一个结点a,通过调整该结点a的指针来删除结点,然而这种算法的时间复杂度为O(n),如下如所示:我们也可以找到该结点i的下一个结点j,将j的内容复制到需要删除的结点i上来覆盖掉其原有的内容,然后再把下一个结点j删掉就可以了!如下图所示:
源代码:
List.h
#ifndef LIST_NODE_H #define LIST_NODE_H namespace ListSpace2 { struct ListNode { int element; ListNode *next; }; ListNode * CreateListNode(int valude); void ConnectListNodes(ListNode *pCurrent, ListNode *pNext); void printListNode(ListNode *pHead); void printList(ListNode *pHead); void printReversingly_Iteratively(ListNode *pHead); void printReversingly_Recursively(ListNode *pHead); void DestoryList(ListNode **pHead); void AddToTail(ListNode ** pHead, int value); void RemoveNode(ListNode ** pHead, int value); } #endif
List.cpp
#include"List.h" #include<iostream> #include<stack> namespace ListSpace2 { ListNode * CreateListNode(int value) { ListNode *pNew = new ListNode(); pNew->element = value; pNew->next = NULL; return pNew; } void ConnectListNodes(ListNode *pCurrent, ListNode *pNext) { if (pCurrent == NULL) std::cout << "Linking Error..." << std::endl; else { pCurrent->next = pNext; } } void printListNode(ListNode *pHead) { if (pHead == NULL) std::cout << "The value of this node is empty" << std::endl; else std::cout << "The value of this node is " << pHead->element << std::endl; } void printList(ListNode *pHead) { if (pHead == NULL) std::cout << "The list is empty" << std::endl; else { ListNode *pNew = pHead; while (pNew != NULL) { std::cout << pNew->element << " "; pNew = pNew->next; } } } void printReversingly_Iteratively(ListNode *pHead) { if (pHead == NULL) { std::cout << "The list is empty" << std::endl; return; } else { std::stack<ListNode *> st; ListNode * pNew = pHead; while (pNew != NULL) { st.push(pNew); pNew = pNew->next; } while (!st.empty()) { std::cout << st.top()->element << " "; st.pop(); } } } void printReversingly_Recursively(ListNode *pHead) { if (pHead != NULL) { if (pHead->next != NULL) printReversingly_Recursively(pHead->next); std::cout << pHead->element << " "; } } void DestoryList(ListNode **pHead) { ListNode *pNew = *pHead; while (pNew != NULL) { *pHead = (*pHead)->next; delete pNew; pNew = *pHead; } } void AddToTail(ListNode ** pHead, int value) { ListNode *pNew = new ListNode(); pNew->element = value; pNew->next = NULL; if (*pHead == NULL) *pHead = pNew; else { //找到最后一个结点 ListNode *node = *pHead; while (node->next != NULL) node = node->next; node->next = pNew; } } void RemoveNode(ListNode ** pHead, int value) { if (pHead == NULL || *pHead == NULL) return; ListNode *pToBeDeleted = NULL; if ((*pHead)->element == value) { pToBeDeleted = *pHead; *pHead = (*pHead)->next; } else { ListNode *node = *pHead; while (node->next != NULL && node->next->element != value) node = node->next; if (node->next != NULL && node->next->element == value) { pToBeDeleted = node->next; node->next = node->next->next; } } if (pToBeDeleted != NULL) { delete pToBeDeleted; pToBeDeleted = NULL; } } }
主函数
#include"List.h" #include<iostream> using std::cout; using std::endl; using namespace ListSpace2; void DeleteNode(ListNode **pHead, ListNode *pToBeDeleted) { if (pHead == NULL || pToBeDeleted == NULL) {//结点为空,删除失败! cout << "删除结点失败!" << endl; return; } //怎么判断被删除的结点是否为单向链表的结点呢? //因为如果该结点不是链表中的结点,那么删除该结点是没有意义的! //链表中有多个结点,且被删除的结点不是尾结点 if (pToBeDeleted->next != NULL) { ListNode *temp = pToBeDeleted->next; pToBeDeleted->element = pToBeDeleted->next->element; pToBeDeleted->next = pToBeDeleted->next->next; delete temp; temp = NULL; } //链表中只有一个结点,删除头结点 else if (*pHead == pToBeDeleted) { delete *pHead; *pHead = NULL; pToBeDeleted = NULL; } //链表中有多个结点,删除最后一个结点 else { ListNode *temp = *pHead; while (temp->next != pToBeDeleted) temp = temp->next; temp->next = NULL; delete pToBeDeleted; pToBeDeleted = NULL; } } //删除多结点链表中非尾结点的链表 void test1() { cout << "===========删除多结点链表中非尾结点的链表=============" << endl; ListNode *list1 = CreateListNode(1); ListNode *list2 = CreateListNode(2); ListNode *list3 = CreateListNode(3); ListNode *list4 = CreateListNode(4); ListNode *list5 = CreateListNode(5); ListNode *list6 = CreateListNode(6); ConnectListNodes(list1, list2); ConnectListNodes(list2, list3); ConnectListNodes(list3, list4); ConnectListNodes(list4, list5); ConnectListNodes(list5, list6); printList(list1); cout << endl; DeleteNode(&list1, list3); printList(list1); cout << endl; } //删除多结点链表中尾结点的链表 void test2() { cout << "===========删除多结点链表中尾结点的链表=============" << endl; ListNode *list1 = CreateListNode(1); ListNode *list2 = CreateListNode(2); ListNode *list3 = CreateListNode(3); ListNode *list4 = CreateListNode(4); ListNode *list5 = CreateListNode(5); ListNode *list6 = CreateListNode(6); ConnectListNodes(list1, list2); ConnectListNodes(list2, list3); ConnectListNodes(list3, list4); ConnectListNodes(list4, list5); ConnectListNodes(list5, list6); printList(list1); cout << endl; DeleteNode(&list1, list6); printList(list1); cout << endl; } void test3() { cout << "===========删除单结点链表中头结点的链表=============" << endl; ListNode *list1 = CreateListNode(1); printList(list1); cout << endl; DeleteNode(&list1, list1); printList(list1); cout << endl; } void test4() { cout << "===========删除空链表中空结点的链表=============" << endl; DeleteNode(NULL, NULL); } int main() { test1(); test2(); test3(); test4(); system("pause"); return 0; }
运行结果:
===========删除多结点链表中非尾结点的链表============= 1 2 3 4 5 6 1 2 4 5 6 ===========删除多结点链表中尾结点的链表============= 1 2 3 4 5 6 1 2 3 4 5 ===========删除单结点链表中头结点的链表============= 1 The list is empty ===========删除空链表中空结点的链表============= 删除结点失败! 请按任意键继续. . .
分析:对于n-1个非尾结点而言,时间复杂度为O(1),对于尾结点而言,时间复杂度为O(n),总的时间复杂度为((n-1)*O(1) + O(n))/n,其结果还是O(1)。
注意:题目中没有判断被删除的结点是否为链表中的结点!
相关文章推荐
- 一个关于if else容易迷惑的问题
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- 一道sql面试题附答案
- C# 超高面试题收集整理
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例