链表的基本操作

由于链表在创建和删除时需要考虑头节点,这里使用二级指针的办法来解决。其他诸如查找,打印可以使用一级指针传参即可。

插入或者删除操作有时会修改实参的指针。比如在这里,当我们往一个空链表插入一个节点时,新插入的节点就是链表的头指针。由于此时会改动头指针,因此必须把pHead参数设为指向指针的指针,否则出了这个函数pHead仍然是一个空指针。
为了强化学习,这里代码全部使用C语言实现:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* 结构体定义 */
struct ListNode
{
    int value;
    ListNode *next;
};

/*根据头结点打印(不需要修改头结点地址,因此一级指针)*/
void printNode(ListNode *myhead)
{
    if (myhead == NULL) return;
    while (myhead)
    {
        printf("%d ", myhead->value);
        myhead = myhead->next;
    }
    printf("\n");
}
void addtoTail(ListNode **pHead, int val)
{
    ListNode *pNew = (ListNode *)malloc(sizeof(ListNode));
    pNew->value = val;
    pNew->next = NULL;

    if (*pHead == NULL)
    {
        *pHead = pNew;
    }
    else {
        ListNode * pNode = *pHead;
        //找尾结点
        while (pNode->next != NULL)
        {
            pNode = pNode->next;
        }
        pNew->next = pNode->next;
        pNode->next = pNew;
    }

}
//去除值(Linus推荐)
void removeNode(ListNode **pHead, int val)
{

    if(pHead == NULL || *pHead == NULL)
    {
        return ;
    }
    ListNode ** curr = pHead; //正在遍历的节点的指针  
    ListNode * entry; //正在遍历的节点
    while (*curr)
    {
        entry = *curr; //注2
        if (entry->value == val)
        {
            /* 删除entry节点 */
            *curr = entry->next; //注3
            free(entry);
            return;
        }
        /* 遍历所有节点的指针 */
        curr = &(entry->next); //注1
    }
}
//去除值(剑指offer推荐)
void RemoveNode(ListNode **pHead, int val)
{

    if (pHead == NULL || *pHead == NULL)
    {
        return;
    }
    ListNode * pToBeDeleted = NULL;
    if ((*pHead)->value == val)
    {
        pToBeDeleted = *pHead;
        *pHead = (*pHead)->next;
    }
    else
    {
        ListNode *pNode = *pHead;
        while (pNode->next != NULL && pNode->next->value != val)
            pNode = pNode->next;
        //找到被删结点的前驱
        if (pNode->next != NULL && pNode->next->value == val)
        {
            pToBeDeleted = pNode->next;
            pNode->next = pToBeDeleted->next;
        }
    }

    if (pToBeDeleted != NULL)
    {
        free(pToBeDeleted);
    }
}
int main()
{
    ListNode *pHead = NULL;
    for (int i = 1; i < 9;i++)
        addtoTail(&pHead, i);
    printf("add to tail:\n");
    printNode(pHead);
    //removeNode(&pHead, 1);
    RemoveNode(&pHead, 1);
    printNode(pHead);
    return 0;
}

上述代码为了突出重点,仅仅有添加节点、删除结点操作。


这里附录其他代码(找到链表的倒数第K个节点):

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
    if (pListHead == NULL) return NULL;
    if (k < 1) return NULL;
    //若k大于结点数,返回NULL
    ListNode * pNode = pListHead;
    unsigned int count = 0;
    while (pNode != NULL)
    {
        pNode = pNode->next;
        count++;
    }
    if (k > count) return NULL;
    //快慢指针都指向head
    unsigned int i = 0;
    ListNode * pNodeFast = pListHead;
    ListNode * pNodeSlow = pListHead;

    while (pNodeFast != NULL && i < k)
    {
        pNodeFast = pNodeFast->next;
        i++;
    }
    if (pNodeFast != NULL)
    {
        //fast走k步后,slow开始走
        while (pNodeFast != NULL)
        {
            pNodeFast = pNodeFast->next;
            pNodeSlow = pNodeSlow->next;
        }

        return pNodeSlow;
    }

    return NULL;
}

猜你喜欢

转载自blog.csdn.net/u013457167/article/details/79629075
今日推荐