单向链表的操作

实现功能:创建链表、头插、尾插、头删除、尾删除、遍历打印、删除预设值相同的节点、重设值、去重、翻转、排序、清空、释放。
测试代码在文章末尾。

#include "linklist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*typedef struct _node{
    int data;
    struct _node* next;
}LinkList_t;
#define LinkList_t List_t
*/
/************************************
 * @b 创建链表的头
 * ***********************************/
List_t* list_creat(void)
{
    List_t* list = NULL;
    if((list = (List_t*)malloc(sizeof(List_t))) == NULL)
    {
        printf("Failed malloc to creat list");
        return NULL;
    }
    list->data = 0;
    list->next = NULL;
    return list;
}
/************************************
 * @b 创建链表的一个节点
 * ***********************************/
List_t* list_creat_node(data_t _data)
{
    List_t* node = (List_t*)malloc(sizeof(List_t));
    if(node == NULL)
    {
        printf("Failed malloc to creat node\n");
        return NULL;
    }
    node->data = _data;                     /*给新结点的数据赋值*/
    node->next = NULL;                      /*把新节点的下一个,指向NULL*/
    return node;
}
/************************************
 * @b 判断链表是否为空
 * ***********************************/
int list_empty(List_t* head)
{
    return head->next == NULL ? -1:0;
}
/************************************
 * @b 头插法
 * ***********************************/
int list_insert_head(List_t* head,data_t val)
{
    List_t* node = list_creat_node(val);    /*创建一个新节点并判断是否成功*/
    if(node == NULL)
    {
        printf("Failed insert head\n");
        return -1;
    }
    node->next = head->next;                /*把新节点的下一个,指向头所指的下一个*/
    head->next = node;                      /*把头所指的下一个,指向新节点*/
    return 0;
}
/************************************
 * @b 尾插法
 * ***********************************/
int list_insert_tail(List_t* head,data_t val)
{
    List_t* node = list_creat_node(val);    /*创建一个新节点并判断是否成功*/
    if(node == NULL)
    {
        printf("Fail insert tail\n");
        return -1;
    }
    while (head->next != NULL)              /*遍历链表找到结尾*/
    {
        head = head->next;
    }
    head->next = node;                      /*把结尾所指的下一个,指向新节点*/
    return 0;
}
/************************************
 * @b 头删
 * ***********************************/
int list_delete_head(List_t* head)
{
    List_t* p = NULL;
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed delete ,list is empty\n");
        return -1;
    }
    p = head->next;
    head->next = head->next->next;          /*把头所指的下一个,指向新节点*/
    free(p);
    p = NULL;                     
    return 0;
}
/************************************
 * @b 尾删
 * ***********************************/
int list_delete_tail(List_t* head)
{
    List_t* p = NULL;
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed delete tail,list is empty\n");
        return -1;
    }
    while (head->next != NULL)              /*遍历链表找到结尾*/
    {
        p = head;                           /*当head是结尾时,p是倒数第二个*/
        head = head->next;
    }
    free(head);
    head = NULL;
    p->next = NULL;
    return 0;
}
/***********************************
  *@b 删除链表当中所有和用户值相同的节点
 **********************************/
int list_delete_data(List_t* head,data_t val)
{
    List_t* p = NULL;
    int res = 0;
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed delete data,list is empty\n");
        return -1;
    }
    while (head->next != NULL)              /*遍历链表到结尾*/
    {
        p = head->next;                     /*复制下一个节点地址*/
        if((p->data) == val)                /*如果节点的值和用户预设值一样*/
        {
            head->next = p->next;           /*把之前的节点链接到这个要删除的节点之后*/
            free(p);                        /*删除这个节点*/
            p = NULL;
            res++;                          /*删除计数+1*/
        }
        else                                /*否则节点的值和用户预设不一样*/
        {
            head = head->next;              /*指向下一个结点*/
        }
    }
    return res;                             /*返回删除节点的个数*/
}
/**********************************
 *@b 重设节点
 * ********************************/
int list_reset_data(List_t* head,int old,int new)
{
    int res = 0;
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed reset data,list is empty\n");
        return -1;
    }
    while (head->next != NULL)              /*遍历链表找到结尾*/
    {
        if(((head->next)->data) == old)     /*找出所有和用户预设值一样的节点并更改数据值*/
        {
            ((head->next)->data) = new;
            res++;
        }
        else
        {
            head = head->next;              /*把头指向新节点*/
        }
    }
    return res;                             /*返回更改节点的个数*/
}

/*****************************************************************
 *
 *                  p                 q
 *   head       head->next        dest->next        q->next      (NULL)
 *               _________        _________        _________
 * |\\\\\\\|    |____1____|      |____1____|      |____2____|
 *                  ^^^     same     ^^^
 *                  |||--------------|||
 *                              (delete this)
 * ******************************************************************/
/**********************************
 *@b 单向链表去重
 * ********************************/
int list_delete_duplicate(List_t* head)
{
    List_t* p = NULL;
    List_t* q = NULL;
    int cnt = 0;
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed delete duplicate,list is empty\n");
        return -1;
    }
    for(;head->next != NULL;head = head->next)
    {
        p = head->next;
        while(p->next != NULL)
        {
            q = p->next;
            if(q->data == head->next->data)
            {
                p->next = q->next;
                free(q);
                q = NULL;
                cnt++;
            }
            else
            {
                p = p->next;
            }
        }
    }
    return cnt;
}
#if 0
int list_delete_duplicate(List_t* head)
{
    List_t* dest = NULL;
    List_t* src = NULL;
    int cnt = 0;
    
    while (head->next != NULL)
    {
        dest = head->next;
        while (dest->next != NULL)
        {
            src = dest->next;
            if(head->next->data == src->data)//不要移动dest,防止跳过后面相同的节点
            {
                dest->next = src->next;     //删除中间相同的节点
                free(src);
                src = NULL;
                cnt++;
            }
            else
            {
                dest = dest->next;          //跳过不相同的节点
            }
        }
        head = head->next;
    }
    return cnt;                             /*返回删除节点的个数*/
}
#endif
/***********************************
  *@b 翻转链表
 **********************************/
int list_reverse(List_t** head)         /*为什么要用到二级指针*/
{                               /*因为我们需要更传参的值,所以要用到传参的地址*/
    List_t* new = NULL;
    List_t* p = NULL;
    if(list_empty(*head))                /*判断链表是否为空*/
    {
        printf("Failed reverse,list is empty\n");
        return -1;
    }
    if((new = list_creat()) == NULL)
    {
        printf("Failed reverse,can not creat new list\n");
        return -1;
    }
    while ((*head)->next != NULL)
    {
        p = (*head)->next;
        (*head)->next = (*head)->next->next;
        p->next = new->next;
        new->next = p;
    }
    free(*head);
    *head = new;
    return 0;
}
/***********************************
  *@b 链表排序
 **********************************/
int list_sort(List_t* head)
{
    List_t* p = NULL;
    List_t* q = NULL;
    if(list_empty(head))                /*判断链表是否为空*/
    {
        printf("Failed sort,list is empty\n");
        return -1;
    }
    for(;head->next->next != NULL;head = head->next)
    {
        p = head->next;
        while (p->next != NULL)
        {
            q = p->next;
            if(q->data < head->next->data)
            {
                p->next = p->next->next;
                q->next = head->next;
                head->next = q;
            }
            else
            {
                p = p->next;
            }
        }
    }
    return 0;
}
/***********************************
  *@b 遍历打印
 **********************************/
int list_print(List_t* head)
{
    if(list_empty(head))                /*判断节点是否为空*/
    {
        printf("Failed print,list is empty\n");
        return -1;
    }
    while (head->next != NULL)              /*遍历链表找到结尾*/
    {
        head = head->next;                  /*打印之前先跳过头(头不存放数据)*/
        printf("%-3d",head->data);
    }
    putchar('\n');
    return 0;
}
/***********************************
  *@b 清空链表
 **********************************/
void list_clean(List_t* head)
{
    List_t* p = NULL;
    while (head->next != NULL)              /*遍历链表找到结尾*/
    {
        p = head->next;                     /*复制头所指的节点地址*/
        head->next = head->next->next;      /*把头指向新节点*/
        free(p);
        p = NULL;
    }
}
/***********************************
  *@b 释放链表
 **********************************/
void list_free(List_t* head)
{
    if(head != NULL)
    {
        list_clean(head);
        free(head);
        head = NULL;
    }
}
posted @ 2022-07-16 20:31  PYPYN  阅读(22)  评论(0编辑  收藏  举报