【链表】无头结点的单链表 前插,后插,删除,显示等

还需改进:

creat_node这个函数应有返回类型,来判断新建结点是否成功,不然主函数中不管成不成功都会访问该节点成员。

改了这个函数,在主函数中create_node后要判断是否成功,不成功就提示并退出函数,退出前别忘了还要释放链表!

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

struct node
{
    int num;

    struct node * next;
};

typedef struct node Node;
typedef struct node * Link;

void create_link(Link *head)   //创建新链表
{
    *head = NULL;
}

void insert_node_head(Link *head,Link new_node)    //前插
{
    new_node->next = *head;
    *head = new_node;
}

void display(Link head)  //按序显示链表
{
    Link p = head;

    if(p == NULL)
    {
        printf("Link is empty!\n");
        return;
    }

    while(p != NULL)
    {
        printf("num = %d\n",p->num);
        p = p->next;
    }
}

void insert_node_tail(Link *head,Link new_node)  //尾插
{
    Link p;

    p = *head;

    if(p == NULL)
    {
        *head = new_node;
        new_node->next = NULL;
    }
    else
    {
        while(p->next != NULL)
        {
            p = p->next;
        }
        p->next =  new_node;
        new_node->next = NULL;
    }
}

void create_node(Link *new_node)  //创建新的节点     给new_node指针分配空间
{
    int count;
    count = 10;        //count保证如果一直申请不了空间的话,他不会一直进入死循环

    do
    {
        *new_node = (Link)malloc(sizeof(Node));
        count--;
    }while(!is_malloc_ok(*new_node) && count);
}

int is_malloc_ok(Link new_node)   //判断给节点分配空间是否有效
{
    if(NULL == new_node)
    {
        printf("error malloc!\n");
        return 0;
    }
    return 1;
}

void insert_node_mid_before(Link *head,Link new_node,int loc)  //在给点节点的前面插入
{
    Link p, q;

    p = q = *head;

    if(p == NULL)
    {
        printf("Link is empty!\n");
        free(new_node);
        return;
    }

    while(p->num != loc && p->next != NULL)
    {
        q = p;
        p = p->next;
    }

    if(p->next == NULL)
    {
        if(p->num == loc)
        {
            new_node->next = p;
            q->next = new_node;
        }
        else
        {
            printf("The node cannot be found!\n");
            free(new_node);
            return;
        }
    }
    else
    {
        if(p == *head)
        {
            new_node->next = *head;
            *head = new_node;
        }
        else
        {
            new_node->next = p;
            q->next = new_node;
        }
    }
}

void insert_node_mid_after(Link head,Link new_node,int loc)  //在给定节点的后面插入
{
    Link p;

    p = head;

    if(p == NULL)
    {
        printf("Link is empty!\n");
        free(new_node);
        return;
    }

    while(p->num != loc && p->next != NULL)
    {
        p = p->next;
    }

    if(p->next == NULL && p->num != loc)
    {
        printf("The node cannot be found!\n");
        free(new_node);
        return;
    }
    else
    {
        new_node->next = p->next;
        p->next = new_node;
    }


}

delete_node(Link *head,int number)  //删除节点(输入number查找到指定节点)
{
    Link p, q;

    p = q = *head;

    if(p == NULL)
    {
        printf("Link is empty!\n");
    }
    else
    {
        while(p != NULL && p->num != number)   //这两个条件不能颠倒!&&是短路运算符,如果颠倒,当p=NULL时判断p的num就会段错误
        {
            q = p;
            p = p->next;
        }
        
        if(p == NULL)
        {
            printf("No such node!\n");
        }
        else
        {
            if(p == *head)
            {
                *head = (*head)->next;
                free(p);
            }
            else
            {
                q->next = p->next;
            }
        }
    }
}

int length(Link head)   //返回链表的节点个数
{
    Link p;
    int count = 0;

    p = head;
    while(p != NULL)
    {
        count++;
        p = p->next;
    }

    return count;

}

void release_link(Link * head)  //删除并释放链表
{
    Link p;
    
    p = *head;

    if(p == NULL)
    {
        printf("Link is empty!\n");
    }
    else
    {
        while(*head != NULL)
        {
            *head = (*head)->next;
            free(p);
            p = *head;
        }
    }
}

void insert_node_sort(Link *head,Link new_node)  //插入后对链表里所有的数排序
{
    Link p, q, k, temp;
    int i, j, count;

    new_node->next = *head;
    (*head) = new_node;   
    if(new_node->next == NULL)
    {
        return;
    }

    count = length(*head);

    for(i = 0; i < count - 1; i++)
    {
        k = *head;
        q = *head;
        p = (*head)->next;
        for(j = 0; j < count - 1 - i; j++)
        {
            if(q->num > p->num)
            {
                q->next = p->next;
                p->next = q;
                if(q == *head)    //不能靠判断k是否指向head
                {
                    *head = p;
                    k = *head;    //注意这边要让k重指向,画图看看
                }
                else
                {
                    k->next = p;
                }
                temp = p;
                p = q;
                q = temp;
            }
            if(q == *head)  //不能靠判断k是否指向head
            {
                q = p;
                p = p->next;
            }
            else
            {
                k = q;
                q = p;
                p = p->next;
            }
        }
    }
}

void insert_node_sort2(Link *head,Link new_node) //插入前链表中的数字是有序的,这次插入的数找正确的地方插入
{
    Link p;
    p = *head;

    if(*head == NULL)
    {
        printf("Link is empty!\n");
    }
    else
    {
        if(new_node->num < p->num)
        {
            new_node->next = *head;
            *head = new_node;
        }
        else
        {
            while(p->next != NULL && p->next->num < new_node->num)
            {
                p = p->next;
            }
            new_node->next = p->next;
            p->next = new_node;
        }
    }
}

int main()
{
    Link head;
    Link new_node;
    int i;
    int location;
    int num;

    srand((unsigned)time(NULL));

    create_link(&head);

    for(i = 0; i < 10; i++)
    {
        create_node(&new_node);
        //new_node = (Link)malloc(sizeof(Node));
        
        new_node->num = rand() % 100;
        //insert_node_head(&head,new_node);

        insert_node_tail(&head,new_node);     //只要指针所指向的内容,一级指针。要改变指针所指向的方向,二级指针
    }

    display(head);
    printf("The length is %d\n\n",length(head));


    /
    create_node(&new_node);

    printf("Please input the new node number:\n");
    scanf("%d",&new_node->num);

    printf("Please input the node you want to insert after:\n");
   // printf("Please input the node you want to insert before:\n");
    scanf("%d",&location);

   // insert_node_mid_before(&head,new_node,location);
    insert_node_mid_after(head,new_node,location);

    display(head);
    printf("The length is %d\n\n",length(head));


    
    create_node(&new_node);

    printf("Please input the node you want to insert:\n");
    scanf("%d",&new_node->num);

    insert_node_sort(&head,new_node);

    display(head);
    printf("The length is %d\n\n",length(head));
    
    /
    create_node(&new_node);

    printf("Please input the node you want to insert:\n");
    scanf("%d",&new_node->num);

    insert_node_sort2(&head,new_node);

    display(head);
    printf("The length is %d\n\n",length(head));

    /
    printf("Please input a node number you want to delete:\n");
    scanf("%d",&num);

    delete_node(&head,num);

    display(head);
    printf("The length is %d\n\n",length(head));

    
    release_link(&head);
    display(head);

    return 0;
}

每次都需要考虑一下头结点这个特殊的位置,不然容易漏。

先插入后排序的函数最好画图看一下各指针的指向(不要想当然),不然也容易错。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值