【c语言之链表的基本操作】

c语言链表的基本操作

路漫漫其修远兮,学无止境
前面学习了c语言的基础知识及一些用法,对于常用的一些函数用法总喜欢忘记,趁有空多记录自己的学习

一.数组的特点

  1. 在内存中,数组是一块连续的区域。 数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间。 以看电影为例 ,假如4个好朋友一起看电影提前预定好了4个座位,相当于在内存中提前申请了4个连续的空间。如果只有3个朋友来,那么就会剩下一个没有使用的空间,如果突然临时又加入了几个朋友一起看电影那么想要坐在一起就很困难,因为我们不能保证相连的座位没有其他的预定。
    2.插入数据和删除数据效率低,插入数据时,这个位置后面的数据在内存中都要向后移。删除数据时,这个数据后面的数据都要往前移动。
    3.随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到给地址的数据。
    4.并且不利于扩展,数组定义的空间不够时要重新定义数组。

二、链表的特点

  1. 在链表操作中与数组最大的优势我认为在与,链表在使用过程中不需要开辟连续的存储空间并且每一个数据都保持后下一个数据的地址,这样的好处就是当我们要就行数据的添加或者删除的时候,只需要将当前的指针先断开指向我们的新节点然后将新节点指向我们下一个数据的地址,这样我们在实践操作过程中大大提升我们的效率更好的节约了我们的内存空间。
    2.查找数据时效率低,因为不具有随机访问性,所以访问某个位置的数据都要从第一个数据开始访问,然后根据第一个数据保存的下一个数据的地址找到第二个数据,以此类推。 要找到第三个人,必须从第一个人开始问起。
    3.不指定大小,扩展方便。链表大小不用定义,数据随意增删。

三、代码演示 ^ ^

/****************数组和链表打印数据****************/

#include <stdio.h>
struct Test
{
        int data;//定义一个结构体成员
        struct Test *next;//指向下一个的指针
};
int main(void)
{
        int array[5]={1,2,3,4,5};
        int i;
        for(i = 0 ; i < 5 ;i++)
        {
                printf("%d ",array[i]);
        }

        printf("\n");
        struct Test t1 ={1,NULL};
        struct Test t2 ={2,NULL};
        struct Test t3 ={3,NULL};
        struct Test t4 ={4,NULL};
        struct Test t5 ={5,NULL};
        t1.next = &t2;
        t2.next = &t3;
        t3.next = &t4;
        t4.next = &t5;
        printf("%d %d %d %d %d ",t1.data,t1.next->data,t1.next->next->data,t1.next->next->next->data,t1.next->next->next->next->data);
        putchar('\n');
}


/*从下面我们不能看出两种方式运行后的结果一样,可能有的人就会想那这样感觉链表的打印岂不是更加复杂,单独从这一个来说的话链表可能是比数组直接打印更复杂一点,但是我们要知道在实际工程的编写中绝对不止data这一个成员,当这些成员变量变多时链表的优势就更能体现了,接着看下面吧*/

在这里插入图片描述

1链表打印改进

void PrintList(struct Test *Head)
{
//重新定义一个结构体让链表头结点指向这个变量,保持头结点不发生改变
        struct Test *p = Head; 
        while(p != NULL)
        {
                printf("%d ",p->data);
                p = p ->next; //指针后移
        }
        printf("\n");
}

int main(void)
{
        int array[5]={1,2,3,4,5};
        int i;
        for(i = 0 ; i < 5 ;i++)
        {
                printf("%d ",array[i]);
        }
        printf("\n");
        struct Test t1 ={1,NULL};
        struct Test t2 ={2,NULL};
        struct Test t3 ={3,NULL};
        struct Test t4 ={4,NULL};
        struct Test t5 ={5,NULL};
        t1.next = &t2; //t1的下一个指向t2的地址
        t2.next = &t3;
        t3.next = &t4;
        t4.next = &t5;
        PrintList(&t1);
        putchar('\n');
        return 0;
}

/*运行结果还是和上面的一样*/

2.链表的增删改查

添加新结点

在这里插入图片描述

删除结点  //注意在我们删除结点后释放该分配的内存空间

在这里插入图片描述

3.总代码

#include <stdlib.h>
//定义结构体Test
struct Test
{
        int data ;//结构体成员
        struct Test *next;//指向下一个数据
};

//头插发创建链表
struct Test *InsertNodeByHead(struct Test *Head ,struct Test *New)
{
        if(Head == NULL)
        {
                Head = New;//如果头结点为空,让新结点成为头结点
        }
        else
        {
        //链表不为空让新结点的下一个指向头结点
                New->next = Head;
                Head = New;//新结点成为头结点
        }
        return Head;
}

//创建链表
struct Test *CreateList(struct Test *Head)
{
        struct Test *New;
        while(1)
        {
       			 //动态开辟空间
                New = (struct Test *)malloc(sizeof(struct Test));
                printf("please input your data:");
                scanf("%d",&(New->data));
                if(New->data == 0)//输入数据为输入值为0时结束
                {
                        printf("Input Finish\n");
                        return Head;
                }
                Head = InsertNodeByHead(Head,New);
        }
        return Head;
}

//在指定数字前面插入数据
struct Test *InsertDataFromBefore(struct Test *Head,int Data ,struct Test *     New)
{
        struct Test *p = Head;
        if(p ->data == Data)
        {
                New->next = Head;
                return Head;
        }
        while(p->next!= NULL)
        {
                if(p->next->data == Data)
                {
                        New ->next =p->next ;
                        p ->next = New;
                        return Head;
                }
                p = p->next;
        }
        return Head;
}


//在指定数字后面插入数据
struct Test *InsertDataFromBehand(struct Test *Head,int Data,struct Test *New)
{
        struct Test *p = Head;
        while(p!= NULL)
        {
                if(p->data == Data)
                {
                        New ->next = p ->next;
                        p->next = New;
                        return Head;
                }
                p = p->next;
        }
        return Head;
}

//打印链表数据
void PrintList(struct Test *Head)
{
        struct Test *p = Head;
        while(p!= NULL)
        {
                printf("%d ",p->data);
                p = p->next;
        }
        printf("\n");
}


//计算链表中的个数
int ListNodeNum(struct Test *Head)
{
        int cen = 0;
        struct Test *p = Head;
        while(p!= NULL)
        {
                cen++;
                p = p->next;
        }
        return cen;
}


//删除链表中指定的元素
struct Test *DeleteNodeData(struct Test *Head ,int Data )
{
        struct Test *p = Head;
        if(p ->data == Data)  //如果头结点为我们要删除的元素
        {
                Head = Head ->next;
                free(p);  //释放内存y元素
                return Head;
        }
        while(p->next!= NULL)
        {
                if(p->next->data == Data)
                {
                        struct Test *temp = p->next;
                        p->next = p->next->next;
                        free(temp);
                        return Head;
                }

                p = p->next;
        }
        return Head;
}


//查找链表中的摸个元素 并将其值和在链表中的下表位置输出
void FindNodeFromList(struct Test *Head ,int Data)
{
        int pos = 1;
        struct Test * p= Head;
        while(p!= NULL)
        {
                if(p->data == Data)
                {
                        printf("Find Data:%d  Postion is %d \n",p->data,pos);
                }
                p = p->next;
                pos++;
        }
}


//链表升序排序
struct Test *BubbleList(struct Test *Head)
{
        struct Test *p = Head;
        struct Test *q;
        while(p!= NULL)
        {
                q = p->next;
                while(q!= NULL)
                {
                        int temp;
                        if(p->data > q->data)
                        {
                                temp = p->data;
                                p->data = q->data;
                                q->data = temp;
                        }
                        q  = q->next;
                }
                p = p ->next;
        }
        return Head;
}


int main(void)
{
         struct Test *head = NULL;//创建一个头结点
         head = CreateList(head);
         PrintList(head);
         struct Test t1 = {100,NULL};
         struct Test t2 = {200,NULL};
         InsertDataFromBehand(head,3,&t1);//在结点3前面插入t1
         PrintList(head);
         InsertDataFromBefore(head ,100,&t2);//在结点2前面插入t2
         PrintList(head);
         BubbleList(head);
         PrintList(head);
         return 0;
}

运行结果

在这里插入图片描述

链表中常用的一些基本操作就是这些了,掌握了基础,相信在后面的学习过程中也会更高效的学习 ^8^

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小殷学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值