c语言编程链表的各种应用

#include <stdio.h>
#include <stdlib.h>
//链表
//1. 定义数据类型
typedef int Data_t;

//2. 定义节点类型
typedef struct node_t 
{
    Data_t data;        //数据域:存储数据本身的
    struct node_t *next;//指针域:存储逻辑关系
}node_t;

//创建空链表
//返回值 失败返回 NULL 
//成功 返回 链表头节点地址
node_t * create_link_list(void)
{
    node_t *p = (node_t *)malloc(sizeof(node_t));
    if(p) p->next = NULL; //空链表 头节点next=NULL
    return p;
}

//链表插入节点
int insert_data(node_t *head, int index, Data_t data)
{
    if(head == NULL) return -1;
    //1. 创建新节点空间
    node_t *q = (node_t *)malloc(sizeof(node_t));
    if(q == NULL) return -2;
    q->data = data;//存储data到q节点中
    //2. p指针 找到index的前一个节点地址    
    node_t *p = head;
    //移动p 指向index前一个节点位置  p 到最末尾仍然没有到index前一个位置
    for(int i=0;i<index && p != NULL ; i++) p = p->next;
    if( p == NULL  ) 
    {//p 到最末尾仍然没有到index前一个位置
        printf("%d 位置 没有在链表上!\n",index);
        return -3;
    }
    else 
    {//p找到index位置的前一个节点的地址 
        //3.将新节点插入到链表中
        q->next = p->next;
        p->next = q;
    }
    return 0;
}

//遍历链表
int show_link_list(node_t *head)
{
    if(head == NULL ) return -1;
    if(head->next == NULL) 
    {
        printf("\n");
        return 0;
    }
    node_t *p = head->next;
    for(  ; p != NULL  ; p=p->next )
      printf("%d ", p->data);
    printf("\n");
}

//给定下标index删除该节点
int del_data(node_t *head, int index)
{
    if(head == NULL || head->next == NULL ) return -1;
    //1.找到index前一个节点地址p
    node_t *p = head;
    for( int i=0;i<index && p->next != NULL ; i++) p=p->next;
    if(p->next == NULL)
    {
        printf("%d 节点没有在链表上,删除失败!\n",index);
        return -2;
    }
    //2. 备份index节点地址 q
    node_t *q = p->next;
    //3. 链接index左右两边的节点
    p->next = q->next;
    //4. 释放节点q节点
    free(q);
    return 0;
}

//拼接两个链表
int connect_link_list(node_t *head1,node_t *head2)
{
    if(head1 == NULL || head2 == NULL) return 0;
    if(head2->next == NULL) return 0;
    node_t *p = head1;
    //找最后节点p
    while(p->next != NULL) p = p->next;
    //拼接2两个节点
    p->next = head2->next;
    //head2 设置为空表 
    head2->next = NULL;
    return 0;
}

//链表翻转
int link_list_Reverse(node_t* head)
{
    if(head ==NULL || head->next == NULL) return -1;
    //1. 头节点 与 数据节点分离
    node_t *p = head->next;
    node_t *q; // 临时中转指针
    head->next = NULL; //头 空链表
    //2. 依次从身体中取出一个节点 头插发到链表
    while(p != NULL) 
    {
        //insert_data(head, 0, p->data); // 存在内存泄露
        q = p;        //备份p到q
        p=p->next;    //移动p
        q->next = head->next; // 头部插入
        head->next = q;     //
    }
    return 0;
}


//1.修改下标位置的值
int change_data(node_t* head, int index , Data_t data)
{
    if(head == NULL|| head->next == NULL) return -1;
    //找到index位置节点指针p
    node_t *p = head -> next;
    for( int i = 0 ; i < index && p != NULL ; p=p->next, i++);
    if(p == NULL)
    {
        printf("%d 节点不在链表上!\n",index);
        return -2;
    }
    //改index节点的内容
    p->data = data;
    return 0;
}
//获取链表的长度
int get_len(node_t *head)
{
    if(head == NULL) return -1;
//    if(head->next == NULL) return 0;
    node_t *p = head;
    int cnt = 0;
    for( ; p->next != NULL ; p=p->next, cnt ++);
    return cnt;
}

//2. 给定data查询第一个data出现的节点地址和下标
int find_data(node_t *head, Data_t data, node_t **answer_addr)
{
    if(head == NULL) return -1;
    if(head->next == NULL) return -2;
    node_t *p = head->next;
    int cnt = 0;
    for(; p != NULL && p->data != data  ;  p=p->next, cnt++);
    if(p==NULL) return -3;
    //answer_addr 为NULL表示调用者 不在乎节点地址
    if(answer_addr )  *answer_addr = p;
    return cnt;    
}

//给定节点地址删除该节点
int del_data_byaddr(node_t *head, node_t* delp)
{
    if(head == NULL || delp == NULL) return -1;
    if(head ->next == NULL ) return -2;
    node_t *p = head;
    for(; p->next != NULL && p->next != delp ; p=p->next);
    if(p->next == NULL) 
    {
        printf("节点%p,未找到!\n",delp);
        return -3; 
    }
    p->next = delp->next;
    free(delp);
    return 0;
}

int main()
{
    //创建一个链表
    node_t *head = create_link_list();
    if(head == NULL) 
    {
        printf("创建失败!!\n");
        return -1;
    }
    else 
      printf("创建成功 head=%p\n",head);

    node_t *head2 = create_link_list();
    if(head2 == NULL) 
    {
        printf("创建失败!!\n");
        return -1;
    }
    else 
      printf("创建成功 head2=%p\n",head2);

    //插入数据到链表
    insert_data(head, 0, 10);
    insert_data(head, 1, 20);
    insert_data(head, 1, 30);
    insert_data(head, 1, 40);
    show_link_list(head);
    
    for(int i=1;i<10;i++) insert_data(head2,0,i);
    
    show_link_list(head2);
    connect_link_list(head,head2);
    show_link_list(head);
    show_link_list(head2);
    
    link_list_Reverse(head);
    show_link_list(head);
    printf("head长度=%d\n",get_len(head));    
    printf("修改head[%d]的值为100!\n", get_len(head)-3);
    change_data(head, get_len(head)-3, 100);
    show_link_list(head);
    
    printf("查找data节点地址和下标!\n");
    node_t * np;
    int ret  = find_data(head, 100, &np);
    if(ret < 0) printf("没有找到100!\n");
    else 
    {
        printf("找到100了,下标为[%d],np=%p, data=%d\n", ret, np, np->data);
        del_data_byaddr(head,np);
        show_link_list(head);
        del_data_byaddr(head,np);
    }
    return 0;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值