【推荐】数据结构:单链表

单链表(不带头节点,不带环)的C语言实现代码
注:建议结合单链表(基础版)一起来看,因为进击版中的一些功能的实现调用了基础版的一些函数(已标出)可以简化功能实现。

//在pos前插入元素,不遍历整个链表

//在pos后插入元素

//删除指定位置元素

//删除指定的元素

//删除指定所有元素

//判断链表是否为空

//求链表长度

//逆序打印单链表

头文件link.h

#pragma once   //防止头文件重复包含

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

#define Datatype char        
typedef struct LinkNode     //定义结构体
{
    Datatype data;           //存储内容
    struct LinkNode* next;     //指向下一个节点
}LinkNode;         

//在pos前插入元素,不遍历整个链表
void LinklistInsert(LinkNode** phead, LinkNode* pos, Datatype value);

//在pos后插入元素
void LinklistInsertAfter(LinkNode** phead, LinkNode* pos, Datatype value);

//删除指定位置元素
void LinklistErase(LinkNode** phead, LinkNode* pos);

//删除指定的元素
void LinklistRemove(LinkNode** phead, Datatype to_remove);

//删除指定所有元素
void LinklistRemoveAll(LinkNode** phead, Datatype to_remove);

//判断链表是否为空
int LinklistEmpty(LinkNode* head);

//求链表长度
size_t LinklistSize(LinkNode* head);

//逆序打印单链表
void LinklistReversePrint(LinkNode* head);

//以上功能实现需要用到的(声明函数如下)

//初始化链表头节点
void LinklistInit(LinkNode** phead);
//链表尾插
void LinklistPushback(LinkNode** phead, Datatype value);
//链表尾删
void LinklistPopback(LinkNode** phead);
//查找元素在链表中的地址
LinkNode* LinklistFind(LinkNode* head, Datatype to_find);

功能实现link.c

//初始化链表头节点
void LinklistInit(LinkNode** phead)
{
    if (phead == NULL)
    {
        printf("空指针");
        return;
    }
    *phead = NULL;
}
//任意位置插入(pos前),不遍历整个链表
void LinklistInsert(LinkNode** phead, LinkNode* pos, Datatype value)
{
    if (phead == NULL||pos==NULL)
    {
        printf("非法输入");
        return;
    }
    //如果pos在第一个位置则调用头插
    if (*phead == pos)
    {
        LinklistPushfront(phead, value);
        return;
    }
    //常规前插,乾坤大挪移
    LinkNode* new = LinklistCreat();   
    new->data = pos->data;        // 把pos值拷贝给新节点
    new->next = pos->next;         //pos指向赋给new指向
    pos->data = value;              //将pos信息修改为新节点信息
    pos->next = new;                //pos指向new   
}
//任意位置插入(pos后)
void LinklistInsertAfter(LinkNode** phead, LinkNode* pos, Datatype value)
{
    if (phead == NULL|| pos == NULL)
    {
        printf("非法输入");
        return;
    }
    if (*phead == NULL )
    {
        printf("空链表");
        return;
    }
    LinkNode* new = LinklistCreat();   
    new->data = value;
    new->next = pos->next;
    pos->next = new;               //pos下一个节点指向新节点
}


//删除指定位置元素
void LinklistErase(LinkNode** phead, LinkNode* pos)
{
    if (phead == NULL || pos == NULL)
    {
        printf("非法输入");
        return;
    }
    if (*phead == NULL)
    {
        printf("空链表");
        return;
    }

    //第一个位置为pos
    if (*phead == pos)
    {
        LinkNode* tmp = *phead;
        *phead = (*phead)->next;
        LinklistDestroy(pos);
        return;
    }
    //常规位置删除
    LinkNode* cur = *phead;
    LinkNode* pre = NULL;
    while (cur != NULL)
    {
        if (cur == pos)
        {
            LinkNode* tmp = cur;  
            pre->next = cur->next;
            LinklistDestroy(tmp);
            return;
        }
        pre = cur;
        cur = cur->next;
    }
    return;
}
//删除指定值的元素
void LinklistRemove(LinkNode** phead, Datatype to_remove) {


    if (phead == NULL) 
    {
        printf("非法输入");
        return;
    }
    if (*phead == NULL) 
    {
        printf("空链表");
        return;
    }
    //删除第一个元素
    if ((*phead)->data == to_remove) {
        LinklistPopfront(phead);  //调用头删
        return;
    }
    LinkNode* cur = LinklistFind(*phead, to_remove);    //调用查找函数,根据元素查找地址
    LinklistErase(phead, cur);                         //调用删除函数, 根据地址删除对应元素
}


//删除指定所有元素
void LinklistRemoveAll(LinkNode** phead, Datatype to_remove) 
{

    if (phead == NULL)
    {
        printf("非法输入");
        return;
    }
    //空链表
    if (*phead == NULL)
    {
        return;
    }
    //删除第一个元素
    if ((*phead)->data == to_remove) 
    {
        LinklistPopfront(phead);  //调用头删
    }

    LinkNode* cur = LinklistFind(*phead, to_remove);  
    while (remove != NULL && cur != NULL)       //遍历删除指定元素
    {
        LinklistErase(phead, cur);
        cur = LinklistFind(*phead, to_remove);
    }
}


//链表为空
int LinklistEmpty(LinkNode* head)
{
    int i = 1;
    if (head == NULL)
    {
        return i;         //链表为空返回1
    }
    return ;               //否则返回随机值
}

//链表长度
size_t LinklistSize(LinkNode* head)    
{
    if (head == NULL)
    {
        printf("非法输入");
        return;
    }
    size_t count = 0;         //定义计数器
    LinkNode* cur = head;
    for (; cur != NULL; cur = cur->next)
    {
        if (cur != NULL)
        {
            count++;
        }
    }
    return count;
}

//逆序打印链表
void LinklistReversePrint(LinkNode* head) 
{


    if (head == NULL) 
    {
        printf("空链表");
        return;
    }

    LinkNode* cur = head;
    if (cur->next != NULL) 
    {
        LinklistReversePrint(cur->next);    //递归实现逆序
    }
    printf("%c\n", head->data);         

}
(以上功能的实现需要调用到以下函数,即附如下函数)
//查找元素在链表中的地址
LinkNode*  LinklistFind(LinkNode* head, Datatype to_find)
{
    if (head == NULL)
    {
        printf("空链表");
        return NULL ;
    }
    LinkNode *cur = head;      
    while (cur != NULL)
    {
        if (cur->data == to_find)  
        {
            return cur;   //找到则返回结构体地址
        }
        cur = cur->next;   //遍历要查找的元素
    }
    printf("没有找到\n");
    return NULL;
}

//链表尾删
void LinklistPopback(LinkNode** phead)
{
    if (phead == NULL)
    {
        printf("非法输入");
        return;
    }
    if (*phead == NULL)
    {
        printf("空链表");
        return;
    }
    //只有一个元素
    if ((*phead)->next == NULL)
    {
        LinkNode* tmp = *phead;  //保存头指针指向
        *phead = NULL;          //置空
        LinklistDestroy(tmp);   //销毁节点
        return;
    }
    //两个及以上元素
    LinkNode* cur = *phead;   
    LinkNode* pre = NULL; 
    while (cur->next != NULL)    //使cur指向最后一个节点
    {                            //使pre指向倒数第二个节点
        pre = cur; 
        cur = cur->next;
    }
    pre->next = NULL;    //尾删,即倒数第二个节点指向空
    LinklistDestroy(cur);  //销毁最后一个节点
}
//链表尾插
void LinklistPushback(LinkNode** phead, Datatype value)
{
    if (phead == NULL)
    {
        printf("非法输入");
        return;
    }
    //空链表尾插
    if (*phead == NULL)
    {
        *phead = LinklistCreat();    //创建节点
        (*phead)->data = value;        //节点赋值
        (*phead)->next = NULL;              //插入空链表即新节点指向空
        return;        
    }
    //常规尾插
    LinkNode* new = LinklistCreat();   //创建新节点
    LinkNode* cur = *phead;          
    new->data = value;
    new->next = NULL;       
    while (cur->next!= NULL)     //使cur指向最后一个节点
    {
        cur = cur->next;
    }
    cur->next = new;          //最后节点的下一个节点即指向新节点
    return;                   
}

功能测试 test.c

#include "link.h"
#include<stdio.h>
#include<stdlib.h>

/************************************************************************
*                            tset
***********************************************************************/

//定义一个宏来打印调试函数提示信息
#define FUNCTION() printf("****************   %s  ************\n" , __FUNCTION__)

void printChar(LinkNode* head ,const char *msg)
{
    if (head == NULL)
    {
        printf("空指针");    
        return;
    }
    printf("%s\n", msg);            
    for (; head != NULL; head = head->next)
    {
        printf("%c\n", head->data);

    }
    printf("\n");
    return;
}

void TestInsert()
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    printChar(head, "尾插a,b,c,d");
    LinklistInsert(&head, head ,'x');
    printChar(head, "a之前插入x");
}

void TestInsertAfter()
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    printChar(head, "尾插a,b,c,d");
    LinklistInsertAfter(&head, head->next, 'x');
    printChar(head, "b之后插入x");
}

void TestErase()
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    printChar(head, "尾插a,b,c,d");
    LinklistErase(&head, head);
    printChar(head, "删除头节点的元素a");

}

void TestRemove()
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    printChar(head, "尾插a,b,c,d");
    LinklistRemove(&head, 'a');
    printChar(head, "删除指定元素a");
}

void TestSize() 
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    LinklistSize(head);
    size_t count = LinklistSize(head);
    printf("count=%lu\n", count);
    printChar(head, "求链表元素的个数");
}

void TestEmpty()
{
    FUNCTION();
    LinkNode* head;
    LinklistInit(&head);

    LinklistPushback(&head, 'a');
    LinklistPushback(&head, 'b');
    LinklistPushback(&head, 'c');
    LinklistPushback(&head, 'd');

    LinklistPopback(&head);
    LinklistPopback(&head);
    LinklistEmpty(head);
    int i = LinklistEmpty(head);
    printf("i=%d\n", i);
    printChar(head, "判断链表是否为空");

}
int main()
{
    TestInsert();
    TestInsertAfter();
    TestErase();
    TestRemove();
    TestEmpty();
    TestSize();
    return 0;

}

这里写图片描述

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/yu876876/article/details/79846854