对单向无头链表的基础操作

我们要求对链表进行如下要求

  1. 初始化链表
  2. 尾插
  3. 尾删
  4. 头插
  5. 头删
  6. 查找元素在链表的位置
  7. 在pos前插入
  8. 在pos后插入
  9. 删除指定位置的元素
  10. 删除指定值的元素
  11. 指定的元素所有都删除掉
  12. 判定链表是否为空
  13. 求链表的元素个数
  14. 逆序打印链表
  15. 不允许遍历链表,在pos前插入
    接下来是在Linux环境下的编程语言:
#pragma once

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

typedef char LinkType;

//创建一个结构体
typedef struct LinkNode{
    LinkType data;//这个就是我们链表的存储数据
    struct LinkNode *next;//这个是链表中每个节点能够串联起来的原因(存储下个节点的地址)
}LinkNode;



//为了后期的代码的维护性,以及代码的健壮性所以我们有必要对那些相比较函数内部独立的程序封装起来
LinkNode* CreateNode(LinkType valaue);//创建节点

void DeleteNode(LinkNode *head);//删除节点

void LinkNodePrint(LinkNode *head,const char* msg);//打印节点



void LinkNodeInit(LinkNode **head);//链表的初始化

LinkNode* LinkNodePushBack(LinkNode **head,LinkType value);//尾插一个节点

void LinkNodePopBack(LinkNode **head);//尾删一个节点

void LinkNodePushTop(LinkNode **head,LinkType value);//头插一个节点

void LinkNodePopTop(LinkNode **head);//头删一个节点

LinkNode* LinkNodeFind(LinkNode *head,LinkType to_find);//找到节点元素并返回元素地址

void LinkNodeInsert(LinkNode **head,LinkNode *pos,LinkType value);//在pos之前插入元素

void LinkNodeInsertAfter(LinkNode **head,LinkNode *pos,LinkType value);//在pos之后插入元素

void LinkNodeErase(LinkNode **head,LinkNode *pos);//删除指定位置的元素

void LinkNodeRemove(LinkNode **head,LinkType value);//删除指定值的节点(有多个只删除第一个)

void LinkNodeRemoveAll(LinkNode **head,LinkType value);//删除所有指定值的节点

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

size_t LinkNodeSize(LinkNode *head);//返回链表的长度

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

void LinkNodeInsert1(LinkNode **head,LinkNode *pos,LinkType value);//不允许遍历链表,在pos之前插入节点

接下来是程序

#include "linknode.h"

//链表初始化
void LinkNodeInit(LinkNode **head)
{
    if(head ==NULL)
    {
        return;
    }
    *head = NULL;//一定要注意初始化是一定要确定这个链表是空的,否则你将头结点置为空,那他后面的节点就找不到了 ,这样就会造成内存泄漏。如果是不为空链表的初始化,记得一定要将后面节点释放掉,再将头结点置为空。
}

//创建节点
LinkNode* CreateNode(LinkType value)
{
    LinkNode *new_node = (LinkNode *)malloc(sizeof(LinkNode));//使用malloc一定要切记,一个malloc对一个free。
    if(new_node == NULL)
    {
        perror("malloc");
        return NULL;
    }
    new_node->next = NULL;
    new_node->data = value;
    return new_node;
}

//删除节点
void DeleteNode(LinkNode *head)
{
    free(head);//malloc之后free(好借好还再借不难)
    head = NULL;
    return;
}

//尾插一个节点
LinkNode* LinkNodePushBack(LinkNode **head,LinkType value)
{
    LinkNode *cur = NULL;//定义这个指针主要作用是遍历链表
    LinkNode *new_node = NULL;//这个就是新插入的节点
    if(head == NULL)
    {
        return NULL;
    }
    new_node = CreateNode(value);//将需要插入的数值保存在节点上
    if(*head == NULL)//空链表的情况
    {
        *head = new_node;
        return *head;
    }
    cur = *head;
    while(cur->next != NULL)//遍历链表找到最后一个节点
    {
        cur = cur->next;
    }
    cur->next = new_node;//将需要插入的节点放入链表的最末尾就行了
    return new_node;
}

//尾删一个节点
void LinkNodePopBack(LinkNode **head)
{
    if(head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *cur = *head;//主要作用还是遍历链表
    LinkNode *to_delete = NULL;//需要被删除的节点指针
    if((*head)->next == NULL)//空链表
    {
        DeleteNode(*head);//空链表删除头结点就行了
        return;
    }
    while(cur->next->next != NULL)
    {
        cur = cur->next;
    }
    to_delete = cur->next;//一通转换
    DeleteNode(to_delete);//最后记得要删除节点啊(malloc申请你的空间一定要记得释放,不然会造成内存泄露)
    cur->next = NULL;
    return;
}

//头插
void LinkNodePushTop(LinkNode **head,LinkType value)
{
    if(head == NULL)
    {
        return;
    }
    LinkNode *cur = CreateNode(value);//头插相比较简单一点  直接将需要差的值插在头  
    cur->next = *head;
    *head = cur;//最后吧头结点转换成最新的节点就行了
}

//头删
void LinkNodePopTop(LinkNode **head)
{
    if(head == NULL)
    {
        return;
    }
    if(*head == NULL)//如果是空链表的  无处可删
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *cur = *head;//删除和头插还是类似的  
    *head = (*head)->next;
    DeleteNode(cur);//一定要记得释放节点啊    free

    return;
}

//返回元素的节点地址
LinkNode* LinkNodeFind(LinkNode *head,LinkType to_find)
{
    LinkNode *cur = NULL;
    if(head == NULL)
    {
        printf("LinkNdoe is null.\n");
        return NULL;
    }
    cur = head;//还是老规矩,遍历用
    while(cur != NULL)
    {
        if(cur->data == to_find)//找到了  返回地址
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;//没找到  返回空值
}

//在pos前插入一个节点
void LinkNodeInsert(LinkNode **head,LinkNode *pos,LinkType value)
{
    LinkNode *cur = *head;
    LinkNode *new_node = NULL;
    if(head == NULL || pos == NULL)//检查传入的参数是否有效
    {
        return;
    }
    if(*head == NULL)//判断是否为空链表
    {
        printf("LinkNode is null.\n");
        return;
    }
    if(cur == pos)
    {
        LinkNodePushTop(head,value);
        return;
    }
    while(cur->next != NULL)//遍历插入节点
    {
        if(cur->next == pos)
        {
            new_node = CreateNode(value);
            cur->next = new_node;
            new_node->next = pos;
            return;
        }
        cur = cur->next;
    }
    return;
}

//在pos之后插入节点(和pos前插入节点类似)
void LinkNodeInsertAfter(LinkNode **head,LinkNode *pos,LinkType value)
{
    if(head == NULL || pos == NULL)
    {
        return;
    }
    if(*head == NULL)
    {
        LinkNodePushTop(head,value);
        return;
    }
    LinkNode *cur = *head;
    LinkNode *new_node = NULL;
    while(cur->next != NULL)
    {
        if(cur == pos)
        {
            new_node = CreateNode(value);
            new_node->next = cur->next;
            cur->next = new_node;
            return;
        }
        cur = cur->next;
    }
    return;
}

//删除节点
void LinkNodeErase(LinkNode **head,LinkNode *pos)
{
    if(head == NULL || pos == NULL)
    {
        return;
    }
    if(*head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *cur = *head;
    while(cur->next != NULL)
    {
        if(cur->next == pos)
        {
            cur->next = pos->next;
            DeleteNode(pos);//**重要**
            return;
        }
        cur = cur->next;
    }
    return;
}

//删除指定元素的节点
void LinkNodeRemove(LinkNode **head,LinkType value)
{
    if(head == NULL)
    {
        return;
    }
    if(*head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *cur = *head;
    LinkNode *new_node = NULL;
    if(cur->data == value)
    {
        LinkNodePopTop(head);
    }
    while(cur->next != NULL)
    {
        if(cur->next->data == value)
        {
            new_node = cur->next;
            cur->next = new_node->next;
            DeleteNode(new_node);
            return;
        }
        cur = cur->next;
    }
    return;
}

//删除所有指定元素的节点
void LinkNodeRemoveAll(LinkNode **head,LinkType value)
{
    if(head == NULL)
    {
        return;
    }
    if(*head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *cur = *head;
    LinkNode *new_node = NULL;
    if(cur->data == value)
    {
        LinkNodePopTop(head);
    }
    while(cur->next != NULL)
    {
        if(cur->next->data == value)
        {
            new_node = cur->next;
            cur->next = new_node->next;
            DeleteNode(new_node);
        }
        cur = cur->next;
    }
    return;
}

//判断链表是否为空 空为0  否则为1
int LinkNodeEmpty(LinkNode *head)
{
    if(head == NULL)
    {
        return 1;
    }
    return 0;
}

//计算链表的长度
size_t LinkNodeSize(LinkNode *head)
{
    size_t count = 0;
    if(head == NULL)
    {
        printf("LinkNode is null.\n");
        return count;
    }
    LinkNode *cur = head;
    while(cur != NULL)
    {
        count++;
        cur = cur->next;
    }
    return count;
}

//逆序打印链表(递归)
void LinkNodeReversePrint(LinkNode *head)
{
    if(head == NULL)
    {
        printf("NULL");
        return;
    }
    LinkNode *cur = head;
    while(cur != NULL )
    {
        LinkNodeReversePrint(cur->next);
        printf("<-[%c|%p]",cur->data,&(cur->data));
        return;
    }
    return;
}

//进阶版的在pos前插入(不需要遍历,但是必须保证pos在链表内)
void LinkNodeInsert1(LinkNode **head,LinkNode *pos,LinkType value)
{
    if(head == NULL || pos == NULL)
    {
        return;
    }
    if(*head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode *new_node = CreateNode(pos->data);
    pos->data = value;
    new_node->next = pos->next;
    pos->next = new_node;
    return;
}

接下来是测试代码


//------------------------------------------------------------------
//测试代码
//------------------------------------------------------------------

#define LINE printf("-------------------------------------------------------\n");

//打印测试函数
void LinkNodePrint(LinkNode *head,const char* msg)
{
    LINE;
    printf("%s",msg);
    printf("\n");
    if(head == NULL)
    {
        printf("LinkNode is null.\n");
        return;
    }
    LinkNode* cur = NULL;
    cur = head;
    while(cur != NULL)
    {
        printf("[%c|%p]->",cur->data,&(cur->data));
        cur = cur->next;
    }
    printf("NULL\n");
    return;
}

//测试函数
void LinkNodeTest()
{
    LinkNode *head = NULL;
    LinkNodeInit(&head);

    LinkNodePushBack(&head,'a');
    LinkNode *pos1 = LinkNodePushBack(&head,'b');
    LinkNodePushBack(&head,'c');
    LinkNodePushBack(&head,'d');
    LinkNodePushBack(&head,'e');
    LinkNodePushBack(&head,'a');
    LinkNodePushBack(&head,'c');
    LinkNodePushBack(&head,'a');
    LinkNodePrint(head,"LinkNodePushBack");

    LinkNodePopBack(&head);
    LinkNodePrint(head,"LinkNodePopBack");

    LinkNodePushTop(&head,'f');
    LinkNodePrint(head,"LinkNodePushTop");

    LinkNodePopTop(&head);
    LinkNodePrint(head,"LinkNodePopTop");

    LinkNodePrint(head,"LinkNodeFind");
    LinkNode *cur = LinkNodeFind(head,'c'); 
    printf("to_find is :[%c|%p]\n",cur->data,&(cur->data));

    LinkNode *pos = LinkNodePushBack(&head,'x');
    LinkNodePushBack(&head,'e');
    LinkNodeInsert(&head,pos,'z');
    LinkNodePrint(head,"LinkNodeInsert");

    LinkNodeInsertAfter(&head,pos,'v');
    LinkNodePrint(head,"LinkNodeInsertAfter");

    LinkNodeErase(&head,pos);
    LinkNodePrint(head,"LinkNodeErase");

    LinkNodeRemove(&head,'v');
    LinkNodePrint(head,"LinkNodeRemove");

    LinkNodeRemoveAll(&head,'a');
    LinkNodePrint(head,"LinkNodeRemoveAll");

    LinkNodePrint(head,"change LinkNode is empty?");
    printf("%d\n",LinkNodeEmpty(head));

    LinkNodePrint(head,"LinkNode:");
    printf("count LinkNode:%d\n",LinkNodeSize(head));

    LinkNodePrint(head,"LinkNode:");
    printf("\n");
    LinkNodeReversePrint(head);
    printf("\n");

    LinkNodeInsert1(&head,pos1,'a');
    LinkNodePrint(head,"LinkNodeInsert1");
}

int main()
{
    LinkNodeTest();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值