c语言数据结构——链表常用算法

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

//本代码的链表是带表头链表,首节点(即表头)不算是元素

struct list
{
    int data;//数据域
    struct list *next;//指针域,指向下一个节点的地址
};

struct list *create_list()//建立一个链表
{
//    struct list *p = (struct list*)malloc(sizeof(struct list));
//    p->data = 0;
//    p->next = NULL;
//    return p;

    return calloc(sizeof(struct list),1);//分配sizeof(struct list)个长度为1的堆内存空间,并自动清零
}

void traverse(struct list *ls)//循环遍历链表
{
    struct list *p = ls;
    while(p)
    {
        printf("%d\n",p->data);
        p = p->next;
    }
}

struct list *insert_list(struct list *ls, int n, int data)//在指定位置插入元素
{
    struct list *p = ls;
    while(p && n--)
    {
        p = p->next;
    }

    if(!p)//有可能链表长度只有5,但是用户却要在100的位置插入数据
        return NULL;
    else
    {
        struct list *node = create_list();//创建一个新的节点
        node->data = data;
        node->next = p->next;
        p->next = node;
        return node;
    }
}

int delete_list(struct list *ls, int n)//删除指定位置元素
{
    struct list *p = ls;
    while(p && --n)//这里用--n是为了while过后,指针指向指定位置的前节点,因为链表无法回头
    {
        p = p->next;
    }

    if(!p)
        return 0;
    else
    {
        struct list *node = p->next;//使用指针指向要删除的节点位置
        if(!node)//如果节点位置无效
            return 0;
        else
        {
            p->next= node->next;
            free(node);
            return 1;
        }
    }
}

int count_list(struct list *ls)//返回链表元素个数(不包含首节点)
{
    int count = 0;
    struct list *p = ls->next;
    while(p)
    {
        count++;
        p = p->next;
    }

    return count;
}

void clear_list(struct list *ls)//清空链表,只保留首节点
{
    struct list *p = ls->next;
    while(p)
    {
        struct list *tmp = p->next;//临时保留下个节点的地址
        free(p);//释放当前节点
        p = tmp;//把p指向下个节点
    }

    ls->next = NULL;//把首节点的指针指向空
}

int empty_list(struct list *ls)//返回链表是否为空
{
    if(ls->next)//如果首节点后还有节点,说明链表不为空
        return 1;
    else
        return 0;
}

struct list *locale_list(struct list *ls, int n)//返回链表指定位置的节点(不包含首节点)
{
    struct list *p = ls->next;
    while(p && n--)
    {
        p = p->next;
    }
    return p;
}

struct list *elem_locale(struct list *ls, int data)//返回数据域等于data的节点
{
    //这是我自己的做法
//    struct list *p = ls->next;
//    while(ls->data!=data)
//    {
//        p = p->next;
//    }

//    if(p)
//        return p;
//    else
//        return NULL;

    //这是别人的做法
    struct list *p = ls->next;
    while(p)
    {
        if(p->data == data)
            break;
        p = p->next;
    }
    return p;
}

int elem_pos(struct list *ls, int data)//返回数据域等于data的节点位置
{
    struct list *p = ls->next;
    int index = 0;
    while(p)
    {
        if(p->data == data);
            break;
        p = p->next;
        index++;
    }
    return index;
}

struct list *last_list(struct list *ls)//得到链表的最后一个节点
{
    //这是我自己的做法
//    struct list *p = ls->next;
//    while(p->next)
//    {
//        p = p->next;
//    }
//    return p;

    //这是别人的做法
    struct list *p = ls->next;
    struct list *pre = p;
    while(p)
    {
        pre = p;
        p = p->next;
    }
    return pre;
}

void merge_list(struct list *ls1,struct list *ls2)//合并两个链表,结果放入ls1中
{
    struct list *p = last_list(ls1);
    p->next = ls2->next;
    free(ls2);
}

void reverse_list(struct list *ls)//逆置链表
{
    if(!ls->next)
        return;//只有首节点,不需要逆置
    if(!ls->next->next)
        return;//除了首节点,就一个有有效节点

    struct list *pre = ls;//前一个节点的指针
    struct list *cur = ls->next;//当前节点的指针
    struct list *next = NULL;//指向下一个节点的指针
    struct list *last = ls->next;//因为逆置完成后,首节点的next就成了最后一个节点
    while(cur)
    {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }

    last->next = NULL;
    ls->next = pre;
}

int main(void)
{
    struct list *first = create_list();//创建链表的首节点
    struct list *second = create_list();//创建下一个节点
    second->data = 2;
    struct list *third = create_list();
    third->data = 3;

    first->next = second;//关联2个节点
    second->next = third;

//    first->next = third;//移除第二个节点,实际上就是把首节点的指针指向第三个节点,然后释放第二个节点
//    free(senond);

    int i;
    for(i = 0;i<10;i++)
    {
        insert_list(first,i,i);//在指定位置插入指定数据
    }

//    delete_list(first,3);//删除第4个节点

//    clear_list(first);//清空链表

    traverse(first);//循环遍历节点

//    printf("list[4] = %d\n",locale_list(first,4)->data);

//    printf("where data equals 4 : %d\n",locale_list(first,4)->data);

//    printf("count of list = %d\n",count_list(first));

    printf("the last elem is : %d\n",last_list(first)->data);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值