左神的书——《程序员代码面试指南》之删除链表的中间节点或a/b节点 c++实现

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值