单链表(创建链表、插入、删除、获取节点数、获取节点数据、摧毁节点)

  • 头文件
//list.h
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED

///线性链表(单链表)的实现及其操作算法
//链表中存储数据的元素类型
typedef int ElemType;
typedef struct Node ListNode;
typedef unsigned short int Bool;

///结构声明
struct Node
{
    //节点数据
    ElemType node_data;
    //指向下一个节点的指针
    ListNode * next_node;
};

///操作函数
//创建单链表
ListNode * CreateListNode(int);
//获取单链表中的节点数据
Bool GetNodeData(ListNode *, int, ElemType *);
//返回单链表节点个数(不包括头结点)
unsigned int NodeNum(ListNode *);
//向单链表中插入节点
ListNode * InsertNodeData(ListNode *, int, ElemType);
//从链表中删除节点
ListNode * DeleteNodeData(ListNode *, int);
//摧毁单链表
Bool DistroyListNode(ListNode *);

#endif // LIST_H_INCLUDED
  • 实现文件
//list.c
#include "list.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

///创建节点数为n的单链表
ListNode * CreateListNode(int n)
{//建立带表头节点的单链表并逆序输入单链表的节点数据
    //为头结点分配空间
    //单链表内所有节点都必须为其分配空间,否则就会产生野指针
    ListNode * list_node = (ListNode *)malloc(sizeof(ListNode));
    printf("please input node data:");
    scanf("%d", &(list_node->node_data));
    //先建立一个带头结点的单链表
    list_node->next_node = NULL;
    int i;
    for(i = 0; i < n - 1; ++i)
    {
        ListNode * new_node = (ListNode *)malloc(sizeof(ListNode));
        scanf("%d", &(new_node->node_data));
        new_node->next_node = list_node;
        list_node = new_node;
    }
    return list_node;
}
///获取单链表节点数据
Bool GetNodeData(ListNode *list_node, int i, ElemType * data_ptr)
{//list_node为头结点的指针成员,i为索引位置(从0开始),data_ptr为指向单链表第i个数据的指针
    //定义循环变量
    int j = 0;
    //寻找第i个节点(从0开始)
    while(list_node && j < i - 1)
    {
        //将节点指针指向下一个节点
        list_node = list_node->next_node;
        //循环变量自增,直到j=i为止
        ++j;
    }
    //若list_node为空指针,则索引位置i超出链表索引范围,返回0
    if(!list_node) return 0;
    //使数据指针的内容为第i个节点的数据
    *data_ptr = list_node->node_data;
    //获取数据成功,返回1
    return 1;
}
///获得单链表节点个数(不包括头结点)
unsigned int NodeNum(ListNode * list_node)
{//list_node为头结点的指针成员
    //节点个数
    int n = 0;
    //若单链表头指针为空指针,则单链表为空表,节点数为0
    if(!list_node) return n;
    //直到单链表指针指向空指针时,说明单链表到达尾部
    while(list_node)
    {
        //单链表指针指向下一个节点
        list_node = list_node->next_node;
        //节点个数加一
        ++n;
    }
    //返回节点个数
    return n;
}
///向单链表中插入节点
ListNode * InsertNodeData(ListNode * list_node, int i, ElemType data)
{//list_node为头结点的指针成员,i为节点插入的索引位置,data为要插入节点的数据成员
    //记录头结点指针
    ListNode * node_ptr = list_node;
    //定义循环变量
    int j = 0;
    //寻找第i - 1个节点(即第i - 2个节点指针成员)
    while(node_ptr && j < i - 2)
    {
        //单链表指针指向下一个节点
        node_ptr = node_ptr->next_node;
        //循环变量自增
        ++j;
    }
    //头指针为空指针,或i超出了索引位置,即i < 1或i > 表长 + 1
    if(!node_ptr) return 0;
    //分配新节点
    ListNode * new_node = (ListNode *)malloc(sizeof(ElemType));
    //令新节点的数据为data(要插入节点的数据)
    new_node->node_data = data;
    //对插入节点位置分情况讨论
    if(i > 1)
    {//插入节点位置大于1时,改变链表节点内容中的指针成员地址,头指针地址不变
        //将节点插入到链表中
        new_node->next_node = (*node_ptr).next_node;
        (*node_ptr).next_node = new_node;
        //插入节点成功,返回头指针地址
        return list_node;
    }
    else
    {//若插入节点位置为1时,改变头指针的地址
        new_node->next_node = node_ptr;
        node_ptr = new_node;
        //节点插入成功,返回头结点指针
        return node_ptr;
    }
}
///从单链表中删除第i个节点
ListNode * DeleteNodeData(ListNode * list_node, int i)
{
    //记录头节点指针
    ListNode * node_ptr = list_node;
    //定义循环变量
    int j = 0;
    //寻找第i - 1个节点(即第i - 2个节点指针成员)
    while(node_ptr && j < i - 2)
    {
        node_ptr = node_ptr->next_node;
        ++j;
    }
    //头指针为空指针,表示i超出了索引位置,即i < 1或i > 表长 + 1
    if(!node_ptr) return 0;
    //对删除位置进行分情况讨论
    if( i > 1)
    {//若删除节点位置大于1,改变链表节点内容中的指针成员地址,头指针地址不变
     //最后返回的头指针内容中的地址不发生变化
        //找到要删除的节点地址(指向要删除节点的指针)
        ListNode * delete_node = (*node_ptr).next_node;
        //将删除节点上一个节点的成员指针指向删除节点的下一个成员
        (*node_ptr).next_node = (*(*node_ptr).next_node).next_node;
        //释放删除节点的内存空间
        free(delete_node);
        //删除成功,返回返回头节点指针成员
        return list_node;
    }
    else
    {//若插入节点位置为1时,改变头指针的地址
        //设删除的节点为第一个节点的地址
        ListNode * delete_node = node_ptr;
        node_ptr = node_ptr->next_node;
        //释放删除节点的内存空间
        free(delete_node);
        //删除成功,返回返回头节点指针成员
        return node_ptr;
    }
}
///摧毁单链表
Bool DistroyListNode(ListNode * list_node)
{
    //获得节点个数
    int n = NodeNum(list_node);
    //若单链表为空表,退出函数,返回0
    if(!list_node) return 0;
    //定义一个新的节点指针,保存头节点指针
    ListNode * node_ptr = list_node;
    while(n)
    {
        //定义循环变量
        int i = 0;
        //找到第n - 1个节点
        while(i < n - 1)
        {
            //将单链表指针指向下一个节点
            list_node = list_node->next_node;
            //循环变量自增
            ++i;
        }
        //释放第n - 1个节点指针指向的内存空间
        free(list_node);
        //重新将节点指针指向头结点指针
        list_node = node_ptr;
        //n = n - 1
        --n;
    }
    //单链表摧毁成功,返回1
    return 1;
}
  • 主程序文件
//main.c
#include "list.h"
#include <stdio.h>
#include <stddef.h>

int main()
{
    //创建链表
    ListNode * list_node = CreateListNode(3);
    //插入节点
    list_node = InsertNodeData(list_node, 2, 20);
    list_node = InsertNodeData(list_node, 1, 30);
    list_node = InsertNodeData(list_node, 1, 40);
    list_node = InsertNodeData(list_node, 3, 50);
    //显示节点数目
    printf("number of node:%d\n", NodeNum(list_node));
    //显示各节点数据
    int i;
    for(i = 0; i < NodeNum(list_node); ++i)
    {
        int NodeData;
        GetNodeData(list_node, i + 1, &NodeData);
        printf("NodeData = %d\t", NodeData);
    }
    putchar('\n');
    //删除节点
    list_node = DeleteNodeData(list_node, 1);
    list_node = DeleteNodeData(list_node, 2);
    list_node = DeleteNodeData(list_node, 3);
    printf("number of node:%d\n", NodeNum(list_node));
    for(i = 0; i < NodeNum(list_node); ++i)
    {
        int NodeData;
        GetNodeData(list_node, i + 1, &NodeData);
        printf("NodeData = %d\t", NodeData);
    }
    //摧毁单链表
    DistroyListNode(list_node);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40579095/article/details/82315062
今日推荐