0
点赞
收藏
分享

微信扫一扫

带头结点的单链表(插入,删除,逆序)

黎轩的闲暇时光 2022-01-08 阅读 39
#include <stdio.h>
#include <stdlib.h>

struct node 
{
    int data;
    struct node *pNext;
};

/*
函数名:  createNode
函数参数:data--结点的数据元素
函数返回值: 返回堆区创建出来的结点首地址
函数作用: 创建一个新结点
*/
struct node* createNode(int data)
{
    struct node *p = (struct node*)malloc(sizeof(struct node));
    if(p == NULL)
    {
        printf("malloc error.\n");
        return NULL;
    }

    //创建成功,初始化该结点
    p->pNext = NULL;
    p->data = data;

    //返回该结点的首地质
    return p;
}

/*
函数名:  insertNodeToListTail
函数参数:pH--插入哪个一个链表的头指针  new--新创建的结点(由函数createNode创建)
函数返回值: void
函数作用: 在链表的尾部插入一个新结点
*/
void insertNodeToListTail(struct node* pH,struct node* new)
{
    struct node*p = pH;

    //走到尾结点
    while(p->pNext != NULL)
    {
        p = p->pNext;//第一次近来指向第一个结点(跳过头结点)
    }
    //到这步时,p指向尾结点
    p->pNext = new;
}


/*
函数名:  insertNodeToListHead
函数参数:pH--插入哪个一个链表的头指针  new--新创建的结点(由函数createNode创建)
函数返回值: void
函数作用: 在链表的头部插入一个新结点
*/
void insertNodeToListHead(struct node* pH,struct node* new)
{
    //新结点指向的下一个结点是原链表的第一个结点
    new->pNext = pH->pNext;

    //头结点指向的下一个结点是新结点(新结点成为第一个结点)
    pH->pNext = new;
}

/*
函数名:  deleteNoteToList
函数参数:pH--删除哪个一个链表的头指针  data--要删除的结点中的数据
函数返回值: 删除成功返回0 删除失败返回-1
函数作用: 删除链表中相同数据的结点(只能删除一个)
*/
int deleteNoteToList(struct node* pH,int data)
{
    struct node* p = pH;
    struct node *pBack = NULL;
    while(p->pNext != NULL)
    {
        pBack = p;  //记录要删除的结点的上一个结点
        p = p->pNext;

        if(p->data == data)
        {
            pBack->pNext = p->pNext; //要删除结点的上一个结点指向要删除结点的下一个结点(跳过要删除的结点)
            free(p);    //切记要释放该结点的堆空间
            return 0;
        }
    }

    printf("can't find this data,delete error.\n");
    return -1;
}

/*
函数名:  traversalList
函数参数:pH--遍历哪个一个链表的头指针
函数返回值: void
函数作用: 遍历链表
*/
void traversalList(struct node *pH)
{
    struct node *p =pH;

    while(p->pNext != NULL)
    {
        p = p->pNext;//第一次执行完之后,p跳过头结点,指向第一个结点
        printf("node data: %d\n",p->data);
    }
}

/*
函数名:  reverseNodeToList
函数参数:pH--逆序哪个一个链表的头指针
函数返回值: void
函数作用: 逆序链表
        将链表中的结点挨个头插入
*/
void reverseNodeToList(struct node *pH)
{
    struct node *p = pH->pNext; //这里需要直接指向第一个结点
    struct node *pBack = NULL;

    if((p == NULL)||(p->pNext == NULL)) //没有有效结点或者只有一个结点时,不需要做任何操作
        return ;

    while(p->pNext != NULL)
    {
        pBack = p->pNext; //记录p的下一个结点,否则等下p插入之后,无法找到p的下一个结点

        if(p == pH->pNext) //原链表中的第一个有效结点在逆序之后为尾结点,其pNext应该指向NULL
        {
            p->pNext = NULL;
        }
        else
        {
            p->pNext = pH->pNext;
        }
        pH->pNext = p;
        p = pBack;   //插入完成之后,应该跳转到原来该结点指向的下一个结点
    }
    //走到这一步的时候,原来的尾结点由于不符合whlie的条件并没有插入,因此需要手动插入
    insertNodeToListHead(pH,p);
}


int main(int argc, char **argv)
{
    //头指针指向头结点,一般情况下,头结点中的数据记录了链表的相关信息而不是数据元素
    struct node *pHeader = createNode(0); //头结点的生成方式与普通结点生成方式不太一样

    insertNodeToListTail(pHeader,createNode(10));
    insertNodeToListTail(pHeader,createNode(20));
    insertNodeToListTail(pHeader,createNode(30));
    insertNodeToListTail(pHeader,createNode(40));
    insertNodeToListTail(pHeader,createNode(50));

    //deleteNoteToList(pHeader,3);

    reverseNodeToList(pHeader);
    traversalList(pHeader);

    return 0;
}
举报

相关推荐

0 条评论