数据结构--单链表(C语言)

单向链表:
链表结点通常包含数据域与指针域,数据域用来存储相关的用户的数据,指针域用来指向下一个结点。访问单向链表,需要从头部(head)开始单向顺序访问,访问终结于指针域(next)为NULL的结点;其存储方式不同于以往的数组,按照非连续地址方式存储。

优点:

链表长度可以实现动态增长,不必像数组一样在创建时确定大小。

采取动态内存分配,不会造成内存浪费。

链表内部结点的插入与删除方便,只需修改相应的next指针。

在删除结点时,只需修改前一结点的指针,并释放本结点,不需要大量移动后面的元素。

实现:

结构体:

//结点结构体
#define Elemtype int
typedef struct node{
    Elemtype value;//数据域
    struct node *next;//指针域
}Node;

链表初始化:

//初始化头结点
//return:返回头结点指针
Node *create_list()
{
    Node *head;
    head = (Node *)malloc(sizeof(Node));//申请结点内存空间
    if(!head)
    {
        printf("Error!");
        exit(1);
    }
    head->next = NULL;
    head->value = 0;
    return head;
}

增加结点

//尾部增加结点
//@num:增加节点数量
//@head:头结点的地址
void add_node(int num,Node **head)
{
    if(!*head)
    {
        printf("The list not create!\n");
        return ;
    }
    Node *p,*q;//p指向新结点 q指向链表尾部
    q = *head;

    while(q->next != NULL)//遍历链表至尾部,在尾部插入新结点
        q = q->next;

    while(num--)
    {
        if(!(p = (Node *)malloc(sizeof(Node))))
        {
            printf("Error!\n");
            exit(1);
        }
        p->next = NULL;
        printf("input value:");
        scanf("%d",&p->value);

        q->next = p;//将新结点连接至链表尾部
        q = p;//q重新指向链表尾部
    }
}

遍历打印

//遍历打印链表
//@head:头结点
void print_list(Node *head)
{
    if(!head)
    {
        printf("The list not create!\n");
        return ;
    }
    Node *p = head;
    while(p->next)//当p的指针域为NULL时,此结点为尾结点
    {
        p = p->next;
        printf("%d\n",p->value);
    }
}

删除第N个结点

//删除第num个结点
//@num:被删除的结点
//@head:头结点
void delete_node(int num,Node **head)
{
    if(!*head)
    {
        printf("The list not create!\n");
        return ;
    }
    Node *q*p = *head;

    //循环中断条件
    //当num == 0终止时,找到结点
    //当p->next == NULL 终止时,链表长度小于或等于num
    while(num-- && p->next != NULL)
    {
        if(!p->next && num > 0)//当p->next == NULL 且 num > 0时,链表长度小于num
            {
                printf("The length is less than num\n");
                return ;
            }
            q = p;      
            p = p->next;
    }
    //循环正常结束后,执行到此处时,代表找到num结点。
    q->next = p->next;
    free(p);
    p = NULL;
}

插入结点

//在num处后插入新结点
//@num:搜索的结点
//@value:新结点的值
//@head:头结点
void insert_node(int num,int value,Node **head)
{
        if(!*head)
    {
        printf("The list not create!\n");
        return ;
    }
    Node *q*p = *head;

    //循环中断条件
    //当num == 0终止时,找到结点
    //当p->next == NULL 终止时,链表长度小于或等于num
    while(num-- && p->next != NULL)
    {
        if(!p->next && num > 0)//当p->next == NULL 且 num > 0时,链表长度小于num
            {
                printf("The length is less than num\n");
                return ;
            }       
            p = p->next;
    }
    q = (Node *)malloc(sizeof(Node));
    q->value = value;

    q->next = p->next;
    p->next = q;
}

销毁链表

//销毁链表
//@head:头结点的指针
void destroy_list(Node **head)
{//因为要修改指针值,所以需要传递指针的指针(二级指针),类似于值传递与址传递
    if(!*head)
    {
        printf("The list not create!\n");
        return ;
    }
    Node *q = *head;
    Node *p = *head;
    //遍历删除头结点以外的结点
    while(p->next)
    {
        p = p->next;
        free(p);
        p = q;
    }
    free(p);//删除头结点
    p = NULL;
    q = NULL;
    *head = NULL;
}

你可能感兴趣的:(数据结构)