您的位置:首页 > 编程语言 > C语言/C++

左神的书——《程序员代码面试指南》之删除链表的中间节点或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的指向,

//所以参数的类型需要指针的引用或二级指针。第二种情况就是普通的删除了。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐