C和C++程序员面试秘笈:30---实现一个单链表的反转

一、要求

  • 给出一个单链表,例如1->2->3->4->5,将其反转变为5->4->3->2->1

二、编码实现

**
 * @description: 反转链表
 * @param: 
       _head: 要反转的链表头指针
 * @return: 反转后的链表头指针
 * @author: Dongshao
 */
Node* reverseList(Node* _head)
{
    if(_head == NULL || _head->_pNext == NULL)
        return NULL;

    Node *p, *q, *r;

    p = _head->_pNext; // 指向第一个节点
    q = p->_pNext;     // 指向第一个节点的后一个节点
    p->_pNext = NULL;  // 将第一个节点的后节点置空

    // 循环判断节点是否为空
    while(q != NULL)
    {
        r = q->_pNext; // 先记住当前节点的下一个节点

        q->_pNext = p; // 将当前节点的下一个指针指向其前节点(逆向指向)
        p = q;         // 将其原先的前节点指针指向自己
        q = r;         // 让自己指向其下一个节点

        // 下面接着下一次判断
    }

    // 让头指针指向遍历中遍历到的最后一个节点
    _head->_pNext = p;

    return _head;
}

三、测试

#include 
#include 

typedef struct node
{
    struct node* _pNext;
    int _data;
}Node;

/**
 * @description: 反转链表
 * @param: 
       _head: 要反转的链表头指针
 * @return: 反转后的链表头指针
 * @author: Dongshao
 */
Node* reverseList(Node* _head)
{
    if(_head == NULL || _head->_pNext == NULL)
        return NULL;

    Node *p, *q, *r;

    p = _head->_pNext; // 指向第一个节点
    q = p->_pNext;     // 指向第一个节点的后一个节点
    p->_pNext = NULL;  // 将第一个节点的后节点置空

    // 循环判断节点是否为空
    while(q != NULL)
    {
        r = q->_pNext; // 先记住当前节点的下一个节点

        q->_pNext = p; // 将当前节点的下一个指针指向其前节点(逆向指向)
        p = q;         // 将其原先的前节点指针指向自己
        q = r;         // 让自己指向其下一个节点

        // 下面接着下一次判断
    }

    // 让头指针指向遍历中遍历到的最后一个节点
    _head->_pNext = p;

    return _head;
}

/**
 * @description: 创建链表
 * @param:
       num: 链表节点数量
 * @return: 创建新链表的头指针
 * @author: Dongshao
 */
Node* createList(int num)
{
    if(num < 0)
        return NULL;

    Node *_head = (Node*)malloc(sizeof(Node));
    _head->_pNext = NULL;

    Node *_tempHead = _head;
    Node *_newNode;
    for(int i = 0; i < num; ++i)
    {
        // 创建新节点
        _newNode = (Node*)malloc(sizeof(Node));
        _newNode->_data = (i+1);
        _newNode->_pNext = NULL;

        // 向后偏移
        _tempHead->_pNext = _newNode;
        _tempHead = _newNode;
        _newNode = NULL;
    }

    return _head;
}

/**
 * @description: 打印链表
 * @param:
       _head: 链表的头结点
 * @return: 无
 * @author: Dongshao
 */
void showList(Node *_head)
{
    if(_head == NULL || _head->_pNext == NULL)
        return;

    Node *_tempNode = _head;

    // 循环打印
    while(_tempNode->_pNext != NULL)
    {
        if(_tempNode->_pNext->_pNext == NULL)
            break;
        else
            printf("%d->", _tempNode->_pNext->_data);

        _tempNode = _tempNode->_pNext;
    }

    // 打印最后一个节点的
    printf("%d\n", _tempNode->_pNext->_data);
}

/**
 * @description: 销毁链表
 * @param:
       _head: 链表的头结点
 * @return: 无
 * @author: Dongshao
 */
void freeList(Node* _head)
{
     if(_head == NULL || _head->_pNext == NULL)
        return;
    
    Node *temp1 = _head->_pNext;
    Node *temp2;
    while(temp1 != NULL)
    {
        temp2 = temp1->_pNext;
        free(temp1);
        temp1 = temp2;
    }
}

int main()
{
    Node *headList = NULL;

    // 创建链表, 并打印链表
    headList = createList(5);
    showList(headList);

    // 反转链表, 并打印链表
    headList = reverseList(headList);
    showList(headList);

    // 释放链表
    freeList(headList);

    return 0;
}

你可能感兴趣的:(C和C++程序员面试秘笈)