左神的书——《程序员代码面试指南》之删除链表的中间节点或a/b节点 c++实现
2017-01-05 00:05
567 查看
//题目一:
//给定链表的头节点head,实现删除链表的中间节点的函数。
//例如:
//不删除任何节点;
//1->2,删除节点1:
//1->2->3,删除节点2;
//1->2->3->4,删除节点2;
//1->2->3->4->5,删除节点3;
//思路:
//首先先找到这个节点,分别利用两个指针,pFast和pSlow,刚开始都是指向头节点,pFast指针走两步,pSlow指针走一步,
//最终pFast指向空了,pSlow指向中间那个节点。(注意:当链表长度为偶数时,中间节点有两个,我们找的是后面那个节点)
//删除这个节点分两种情况进行,第一种是这个节点是头节点,此时要将链表的头指针指向这个节点的下个节点,要在函数里修改主函数中pHead的指向,
//所以参数的类型需要指针的引用或二级指针。第二种情况就是普通的删除了。
//给定链表的头节点head,实现删除链表的a/b节点的函数。例如:
// 链表:1->2->3->4->5,假设a/b的值为r;
// 如果r = 0,不删除任何节点;
// 如果r 在区间(0,1/5]上,删除节点1;
// 如果r 在区间(1/5,2/5]上,删除节点2;
// 如果r 在区间(2/5,3/5]上,删除节点3;-
// 如果r 在区间(3/5,4/5]上,删除节点4;
// 如果r 在区间(4/5,1]上,删除节点5;
// 如果r大于1,不删除任何节点。
//思路 :通过分析发现链表的长度乘以(0,1/5] == (0,1] 删除节点1. (注:我们认为节点1是第一号节点,不是第0号节点,代码中是把它看成从位置1开始的)
/* (1/5,2/5]==(1,2],删除节点2;
(2/5,3/5] ==(2,3],删除节点3;
(3/5,4/5] ==(3,4], 删除节点4;
(4/5,1] ==(4,5], 删除节点5;*/
//能发现删除节点都是向上取整的。
//给定链表的头节点head,实现删除链表的中间节点的函数。
//例如:
//不删除任何节点;
//1->2,删除节点1:
//1->2->3,删除节点2;
//1->2->3->4,删除节点2;
//1->2->3->4->5,删除节点3;
//思路:
//首先先找到这个节点,分别利用两个指针,pFast和pSlow,刚开始都是指向头节点,pFast指针走两步,pSlow指针走一步,
//最终pFast指向空了,pSlow指向中间那个节点。(注意:当链表长度为偶数时,中间节点有两个,我们找的是后面那个节点)
//删除这个节点分两种情况进行,第一种是这个节点是头节点,此时要将链表的头指针指向这个节点的下个节点,要在函数里修改主函数中pHead的指向,
//所以参数的类型需要指针的引用或二级指针。第二种情况就是普通的删除了。
#include<iostream> using namespace std ; #include <cassert> struct Node { int value; struct Node * Next; Node(int data):value(data),Next(NULL) { } }; void DelMidNode(Node* &pHead) { assert(pHead); Node *pFast = pHead->Next; //如果pFast = pHead ,则能找到中间节点后面那个节点。 Node *pSlow = pHead; while (pFast != NULL && pFast->Next != NULL) { pFast = pFast->Next->Next; pSlow = pSlow->Next; } //while循环走完,pslow指向中间那个节点。 //删除找到的节点。 if (pSlow == pHead) //找到的是头节点 { Node *pDel = pHead; pHead = pHead->Next; delete pDel; } else { Node *pCur = pHead; while (pCur->Next != pSlow) { pCur = pCur->Next; } pCur->Next = pSlow->Next; delete pSlow; } } int main() { //这里只是单纯的分配节点,不释放节点,要不然篇幅太长了。毕竟节点的分配和释放不是重点。 Node *n1 = new Node(1); Node *n2 = new Node(2); Node *n3 = new Node(3); Node *n4 = new Node(4); Node *n5 = new Node(5); Node *n6 = new Node(6); Node *pHead1 = n1; n1->Next = n2; n2->Next = n3; n3->Next = n4; n4->Next = n5; n5->Next = n6; DelMidNode(pHead1); Node *pCur = pHead1; while (pCur) { cout << pCur->value <<endl; pCur = pCur->Next; } cout << "hello..." <<endl; system("pause"); return 0; }//进阶题目:
//给定链表的头节点head,实现删除链表的a/b节点的函数。例如:
// 链表:1->2->3->4->5,假设a/b的值为r;
// 如果r = 0,不删除任何节点;
// 如果r 在区间(0,1/5]上,删除节点1;
// 如果r 在区间(1/5,2/5]上,删除节点2;
// 如果r 在区间(2/5,3/5]上,删除节点3;-
// 如果r 在区间(3/5,4/5]上,删除节点4;
// 如果r 在区间(4/5,1]上,删除节点5;
// 如果r大于1,不删除任何节点。
//思路 :通过分析发现链表的长度乘以(0,1/5] == (0,1] 删除节点1. (注:我们认为节点1是第一号节点,不是第0号节点,代码中是把它看成从位置1开始的)
/* (1/5,2/5]==(1,2],删除节点2;
(2/5,3/5] ==(2,3],删除节点3;
(3/5,4/5] ==(3,4], 删除节点4;
(4/5,1] ==(4,5], 删除节点5;*/
//能发现删除节点都是向上取整的。
#include<iostream> using namespace std ; #include <cassert> struct Node { int value; struct Node * Next; Node(int data):value(data),Next(NULL) { } }; void DelByRatNode(Node* &pHead, int a, int b) //删除a/b的节点。 { assert(pHead); if (a < 1 || a > b) { return; } Node *pCur = pHead; int num = 0; while (pCur) { num++; pCur = pCur->Next; } int DelNum = (int)ceil( ((double)a/(double)b * num) ); //求出要删除的节点。ceil是向上取整函数, if (DelNum == 1) //如果要删除的是第一个节点,(其实就是0号位置)。 { Node *pDel = pHead; pHead = pHead->Next; delete pDel; } pCur = pHead; if (DelNum > 1) { while (--DelNum != 1) //找到这个节点的前置节点,所以是前置--, { pCur = pCur->Next; } Node *pDel = pCur->Next; pCur->Next = pCur->Next->Next; delete pDel; } } int main() { //这里只是单纯的分配节点,不释放节点,要不然篇幅太长了。毕竟节点的分配和释放不是重点。 Node *n1 = new Node(1); Node *n2 = new Node(2); Node *n3 = new Node(3); Node *n4 = new Node(4); Node *n5 = new Node(5); Node *n6 = new Node(6); Node *pHead1 = n1; n1->Next = n2; n2->Next = n3; n3->Next = n4; n4->Next = n5; n5->Next = n6; DelByRatNode(pHead1,1,6); Node *pCur = pHead1; while (pCur) { cout << pCur->value <<endl; pCur = pCur->Next; } cout << "hello..." <<endl; system("pause"); return 0; }
相关文章推荐
- 左神的书——《程序员代码面试指南》之删除链表的倒数第k个节点 c++实现
- 左神的书——《程序员代码面试指南》之逆置单链表或双链表 c++实现
- C++删除链表中间节点的方法
- C++实现遍历链表一次求出中间的节点
- 左神的书——《程序员代码面试指南》之打印两个有序链表的公共部分 c++实现
- 建立一个带附加头结点的单链表.实现测长/打印/删除结点/插入结点/逆置/查找中间节点/查找倒数第k个节点/判断是否有环
- [google面试CTCI] 2-3 只给定链表中间节点指针,如何删除中间节点?
- 链表的插入删除和查找_C++实现
- 实现链表的逆序输出和删除某节点
- 【数据结构】C语言实现链表节点的插入和删除
- 编码实现环状单向链表(尾指针直接指向头指针,中间没有空节点),去除连续的重复元素的操作。
- C语言实现双向链表删除节点、插入节点、双向输出等操作
- 二叉树的建立、节点查找以及节点删除C和C++实现
- 数据结构_队列_用链表动态建立释放节点实现队列各种操作_C++实现
- 设计一个整型链表类list,能够实现链表节点的插入、删除、以及链表数据的输出操作。
- c++中对单链表操作---合并两个链表&&单链表逆序&&删除链表中的中间结点
- 编程实现单链表和双链表删除节点
- [面试] - 在单链表末尾添加一个节点 C++ 实现
- 带头节点的单链表删除 - c++
- 链表的基本操作 从头部插入 尾部插入 中间插入 删除节点