单链表(不带表头结点)的插入、删除、排序、倒序

#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 is_malloc_ok(Link new_node)                             //动态分配空间是否成功
{
    if(new_node == NULL)
    {
        printf("malloc error!\n");
        exit(-1);
    }
}

void create_new_node(Link * new_node)                              //创建结点,需要分配空间和判断是否分配成功
{
    *new_node = (Link)malloc(sizeof(Node));
    is_malloc_ok(*new_node);
}

void insert_node_tail(Link * head,Link new_node)            //尾部插入,参数与头部插入一致
{
    Link p;
    p = *head;                                                                        //定义一个指针为头指针
    if(*head == 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 release_link(Link * head)                                          //链表空间的释放
{
    Link p;
    p = *head;
    while(*head != NULL)                                               //让头指针指向第二个结点,然后释放第一个结点
    {
        *head = (*head)->next;                                                //循环到最后一个
        free(p);
        p = *head;
    }
}

void display_link(Link head)                              //链表的显示
{
    Link p;
    p = head;

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

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

void insert_node_mid_head(Link * head,Link new_node,int loc)       //中间插入( 头部插入)
{                                                                        //多了一个参数,即寻找相要插入在哪个数的哪个位置
    Link p,q;
    if(NULL == *head)                                               //如果链表为空的一种情况
    {
        *head = new_node;
        new_node->next = NULL;
    }
    else                                                                      //定义俩个指针
    {
        q = *head;
        p = (*head)->next;
        if(q->num == loc)                                          //第一个结点为想要插入的结点位置
        {
            new_node->next = *head;
            *head = new_node;
        }
        else
        {
            while(p != NULL && p->num != loc)              //寻找想要插入的位置,直到找到为止
            {
                q = p;
                p = p->next;
            }
            if(p == NULL)                                            //如果没有要找的数,者插入在链表的尾部
            {
                q->next = new_node;
                new_node->next = NULL;
            }
            else                                                     //找到要插入的结点位置
            {
                q->next = new_node;
                new_node->next = p;
            }
        }
    }
}

void insert_node_mid_tail(Link * head,Link new_node,int loc)    //中间插入(尾部插入),方法同上
{
    Link q,p;

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

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

}


void delete_node(Link * head,int num)                             //删除结点
{
    Link q,p;
    if(*head == NULL)
    {
        printf("Link is empty! no such node!\n");
        return;
    }
    if((*head)->num == num)                                          //第一个结点为想要删除的结点情况
    {
        p = *head;
        *head = (*head)->next;
        free(p);
    }
    else                                                                 //找到想要删除的结点,利用定义的俩个指针,q在前p在后
    {
        q = *head;
        p = (*head)->next;
        while(p != NULL && p->num != num)
        {
            q = p;
            p = p->next;
        }
        if(p == NULL)
        {
            printf("no such node!\n");
        }
        else
        {
            q->next = p->next;                                       //找到要删除的结点,让q指向p的下一个结点,释放p结点
            free(p);
        }
    }
}


void insert_node_sort_asc(Link *head,Link new_node)       //顺序插入,这里演示从小到到的排序
{
    Link q,p;
    if(*head == NULL)
    {
        *head = new_node;
        new_node->next = NULL;
    }
    else                                                                                // 想要的插入的结点比头结点小,则插入在头部
    {
        q = *head;
        p = (*head)->next;
        if((*head)->num > new_node->num)
        {
            new_node->next = *head;
            *head = new_node;
        }
        else                                                                            //寻找到比插入结点大的结点,插入在这个数前面
        {                                                                                //同样的
            while(p != NULL && p->num < new_node->num)
            {
                q = p;
                p = p->next;
            }
            q->next = new_node;
            new_node->next = p;
        }
    }
}

void reverse_link(Link *head)                                                                       //倒序输出,需要定义三个指针
{
    Link p1,p2,p3;
    if(*head == NULL)
    {
        printf("Link is empty!\n");
        return;
    }
    if((*head)->next == NULL)
    {
        return;
    }
    p1 = *head;
    p2 = (*head)->next;
    p3 = p2->next;
    while(p3 != NULL)
    {
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        p3 = p3->next;
    }
    p2->next = p1;
    (*head)->next = NULL;
    *head =p2;
    return;
}

int main()
{
    int num;
    int loc;
    int i;
    Link head = NULL;
    Link new_node = NULL;

    srand((unsigned)time(NULL));                                          //生成任意数


    create_link(&head);                                                         //创建链表
    for(i = 0;i < 10;i++)
    {
        create_new_node(&new_node);                                 //创建结点
         new_node->num = rand() % 100;                               //结点的值域为任意数
        // insert_node_head(&head,new_node);                    //头部插入
          //   insert_node_tail(&head,new_node);                    //尾部插入
    insert_node_sort_asc(&head,new_node);                     //排序插入,从小到大或从大到小的顺序
    }

    display_link(head);                                                         //显示链表内容

   /* printf(":\n");                                                           
     scanf("%d",&loc);                                               
    printf("\n");

    create_new_node(&new_node);                                      //创建一个结点,插入已有的链表,值域为100
    new_node->num = 100;
    insert_node_mid_head(&head,new_node,loc);            //插入在这个数的头部
   //insert_node_mid_tail(&head,new_node,loc);      //插入在这个数的尾部,这俩种插入也叫中间插入

    display_link(head);*/

   /* printf("please  input num to delete!\n");           //输入一个想要删除的结点的数
    scanf("%d",&num);

    delete_node(&head,num);                                             //删除结点

    display_link(head);*/


//    display_link(head);

printf("\n");

    reverse_link(&head);                                      //倒序输出单链表
    display_link(head);
    release_link(&head);                                  //链表空间的释放

    display_link(head);


    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值