//题目一:
//给定链表的头节点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;
}