您的位置:首页 > 职场人生

链表相关的热点面试题(一)

2017-05-15 13:28 274 查看
先把相关的题目给出来

1. 从尾到头打印单链表

2. 删除一个无头单链表的非尾节点

3. 在无头单链表的一个非头节点前插入一个节点

4. 逆置/反转单链表

5. 单链表排序

6. 合并两个有序链表,合并后依然有序

7. 查找单链表的中间节点, 要求只能遍历一次链表

先把单链表结构给出来

template<typename T>
struct Node
{
Node<T>* _next;
T _value;
Node(const T& value = T())
:_value(value)
, _next(NULL)
{}
};


从尾到头打印单链表

这就是最简袋的递归思想。

void ReversePrint(const Node<int>* node)
{
if (node == NULL)
return;
ReversePrint(node->_next);
cout << node->_value << " ";
}


删除一个无头单链表的非尾节点(链表的O(1)删除)

乍一看是不是有点没头绪,甚至都不知道题目是什么意思。

一般的我们要删除一个单链表节点pos,都是找到它的前一个节点prev,然后让prev->next指向pos->next,但是这里说要删除一个无头节点,也就是我们没办法通过遍历找到pos的前一个节点,那怎么办呢?

其实思路也是很简单的,我们可以通过赋值的方式,只对节点数据就行改变,可以把要删除节点pos->next的数据,也就是del->value赋值给pos,然后再删除del这个节点就好了。



void EraseNotTail(Node<int>* node)
{
assert(node&&node->_next);//去除空节点和尾节点的情况
Node<int>* del = node->_next;
node->_value = del->_value;
node->_next = del->_next;
delete del;
}


这道题也叫做 链表的O(1)删除。

在无头单链表的一个非头节点前插入一个节点

刚做完上面那道删除,这又来插入是不是感觉很简单。

思路是一样的:

我们先申请一个节点newnode,然后将newnode插入到pos后面,然后交换newnode和pos的数据。



void InsertFrontNode(Node<int>* node)
{
assert(node);//去除节点为空情况
Node<int>* newnode = new Node<int>(5);
newnode->_next = node->_next;
node->_next = newnode;
swap(node->_value, newnode->_value);
}


逆置/反转单链表



void Reverse(Node<int>*& head)
{
assert(head!=NULL);
Node<int>* newhead = head;
Node<int>* cur = head->_next;
head->_next = NULL;
while (cur)
{
Node<int>* tmp = cur->_next;
cur->_next = newhead;
newhead = cur;
cur = tmp;
}
}


单链表排序( 冒泡排序)

其实就和普通的冒泡排序一样

void BubbleSort(Node<int>* head)
{
assert(head);
if (head->_next== NULL)
return;
Node<int>* cur = head;
Node<int>* tail = NULL;
while (cur != tail)     //当尾指针不等于头指针时进行冒泡
{
while (cur->_next != tail)   //控制cur指针最后到的位置是倒数第二个节点
{

if (cur->_value > cur->_next->_value)
{
swap(cur->_value, cur->_next->_value);
}
cur = cur->_next;
}
tail = cur;
cur = head;
}
}


合并两个有序链表,合并后依然有序

这里是用递归的思想,每次进来都找数据小的那个节点,让小的节点最为新的头节点,知道有一个链表走到NULL位置。

Node<int>* MergeTwoList(Node<int>*& head1, Node<int>*& head2)
{
if (head1 == NULL)
return head2;
if (head2 == NULL)
return head1;
Node<int>* newhead = head1->_value < head2->_value ? head1 : head2;
if (newhead == head1)
newhead->_next = MergeTwoList(head1->_next, head2);
if (newhead == head2)
newhead->_next = MergeTwoList(head1, head2->_next);
return newhead;
}


查找单链表的中间节点, 要求只能遍历一次链表

这个就是快慢指针,快指针一次走两步,慢指针一次走一步。

最后快指针fast走到尾节点的时候,慢指针刚好到中间节点。



Node<int>* FindMidNode( Node<int>* head)
{
assert(head);
Node<int>* slow= head;
Node<int>* fast = head;
while (fast != NULL)
{
if(fast->next==NULL)
break;
fast=fast->_next->_next;
slow = slow->_next;
}
return slow;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息