先把相关的题目给出来
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;
}