2021-06-20嵌入式学习杂记---链表

1、链表概念
链表–数据结构–>数据存放的思想
链表是一种上一个元素的引用指向下一个元素的存储结构,链表通过指针来连接元素与元素,链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

struct Test
{
        int data;  //数据域
        struct Test *next; //指针域
};
int main()
{
        struct Test t1 = {1, NULL};
        struct Test t2 = {2, NULL};
        struct Test t3 = {3, NULL};

        t1.next = &t2;
        t2.next = &t3;
		return 0;
}

2、链表与数组的区别
1)链表是链式的存储结构;数组是顺序的存储结构。
2)链表通过指针来连接元素与元素,数组则是把所有元素按次序依次存储。
3)链表的插入删除元素相对数组较为简单,不需要移动元素,且较为容易实现长度扩充,但是寻找某个元素较为困难;数组寻找某个元素较为简单,但插入与删除比较复杂,由于最大长度需要再编程一开始时指定,故当达到最大长度时,扩充长度不如链表方便。

从逻辑结构来看
1.数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素

从内存存储来看
1.(静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小
2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦

从上面的比较可以看出,如果需要快速访问数据,很少或不插入和删除元素,就应该用数组;相反, 如果需要经常插入和删除元素就需要用链表数据结构了。
3、链表静态添加和遍历

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

struct Test
{
        int data;
        struct Test *next;
};
void printLink(struct Test *head)//链表遍历
{
        struct Test *point;
        point = head;
        while(point != NULL){
                printf("%d", point->data);
                point = point->next;
        }
        putchar('\n');
}
int main()
{
        struct Test t1 = {1, NULL};
        struct Test t2 = {2, NULL};
        struct Test t3 = {3, NULL};
        t1.next = &t2;
        t2.next = &t3;
        printLink(&t1);//链表遍历
        return 0;
}

4、统计链表个数及链表查找

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

struct Test
{
        int data;
        struct Test *next;
};
void printLink(struct Test *head)//链表遍历
{
        struct Test *point;
        point = head;
        while(point != NULL){
                printf("%d", point->data);
                point = point->next;
        }
        putchar('\n');
}
int totalNum(struct Test *head)//统计链表个数
{
        int cnt=0;
        struct Test *p = head;
        while(p != NULL){
                cnt++;
                p=p->next;
        }
        return cnt;
}
int searchLink(struct Test *head,int data)//链表的查找
{
        struct Test *p=head;
        while(p != NULL){
                if(p->data == data){
                        return 1;
                }
                p=p->next;
        }
        return 0;
}

int main()
{
        int ret;
        struct Test t1 = {1, NULL};
        struct Test t2 = {2, NULL};
        struct Test t3 = {3, NULL};
        t1.next = &t2;
        t2.next = &t3;
        printLink(&t1);
        ret = totalNum(&t1);
        printf("total is %d\n",ret);
        ret = searchLink(&t1,2);
        if(ret == 0){
                printf("no 2\n");
        }else{
                printf("has 2\n");
        }
        return 0;
}

5、 链表从指定节点后方插入新节点
链表 1-- 2-- 3 – 4—5
在3结点后插入新的100
1)找到3
2)new->next =3 ->next;
3) 3->next =new;

int insertBehind(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 1;
                }
                p = p->next;
        }
        return 0;
}
void printLink(struct Test *head)
{
        struct Test *point;
        point = head;
        while(point != NULL){
                printf(" %d ", point->data);
                point = point->next;
        }
        putchar('\n');
}
int main()
{
		int ret;
        struct Test t1 = {1, NULL};
        struct Test t2 = {2, NULL};
        struct Test t3 = {3, NULL};
        struct Test new = {100, NULL};

        t1.next = &t2;
        t2.next = &t3;
        ret = insertBehind(&t1,3,&new);
        printLink(&t1);
		return 0;
}
//运行结果: 1 2 3 100

6、链表从指定节点前方插入新节点
链表 1-- 2-- 3
在1结点前插入新的101
1)在第一个结点前插入101,new->next = 1,此时链表的头发生了变化
在3结点前插入新的结点102
1)找到2->next->data =3
2)new->next =2->next;
3) 2->next =new;

struct Test *insertFor(struct Test *head, int data, struct Test *new)//因为会改头部,返回链表指针
{
        struct Test *p = head;
        if(p->data == data){ //在链表头部插入新节点
                new->next = p;
                return new;
        }
        while(p->next != NULL){  //插入的新节点不是头部
                if(p->next->data == data){
                        new->next=p->next;
                        p->next=new;
                        return head;
                }
                p=p->next;
        }
        return head;
};
int main()
{
        int ret;
        struct Test *head = NULL;
        struct Test t1 = {1, NULL};
        struct Test t2 = {2, NULL};
        struct Test t3 = {3, NULL};
        struct Test t5 = {100, NULL};

        t1.next = &t2;
        t2.next = &t3;
        head = &t1;
        ret = insertBehind(head,3,&t5);
        printLink(head);

        struct Test new={101, NULL};
        head = insertFor(head, 1, &new);
        printLink(head);

        struct Test new2={102, NULL};
        head = insertFor(head, 3, &new2);
        printLink(head);
		return 0;
}
//运行结果:
 // 1  2  3  100 
 //101  1  2  3  100 
 //101  1  2  102  3  100 

7、链表删除指定节点
链表 1-- 2-- 3
1)删除第一个结点,改头
2)要删除的不是头,找到要删除的2, (1) 1->next->data=2, (2) 1->next=1->next->next

struct Test *deleteNum(struct Test *head, int data)
{
        struct Test *p =head;
        if(p->data == data){
                head = p->next;
                return head;
        }
        while(p != NULL){
                if(p->next->data == data){
                        p->next=p->next->next;
                        return head;
                }
                p=p->next;
        }
        return head;
}
//运行结果: 1  3

8、链表动态创建之头插法

void printLink(struct Test *head)
{
        struct Test *point;
        point = head;

        while(point != NULL){
                printf(" %d ", point->data);
                point = point->next;
        }
        putchar('\n');
}

struct Test *insertHead(struct Test *head)
{
        struct Test *new;
        while(1){
                new = (struct Test *)malloc(sizeof(struct Test));//每次开辟空间
                printf("input your num\n");
                scanf("%d",&(new->data));
                if(new->data ==0){           //输入0退出
                        printf("0 quit\n");
                        return head;
                }
                if(head == NULL){         //链表为空时,插入
                        head=new;
                }else{
                        new->next=head;     //头插法,新的下一个为头,插完后,把新的名为头
                        head=new;
                }
        }
        return head;
};
int main()
{
        struct Test *head = NULL;
        head = insertHead(head);    //返回值为头
        printLink(head);
        return 0;
}

9、链表动态创建之尾插法

void printLink(struct Test *head)
{
        struct Test *point;
        point = head;

        while(point != NULL){
                printf(" %d ", point->data);
                point = point->next;
        }
        putchar('\n');
}

struct Test *insertBehind(struct Test *head, struct Test *new)
{
        struct Test *p=head;
        if(p == NULL){
                head = new;
                return head;
        }
        while(p->next != NULL){
                p = p->next;
        }
        p->next = new;
        return head;
}

struct Test *creatLink(struct Test *head)
{
        struct Test *new;
        while(1){
                new = (struct Test*)malloc(sizeof(struct Test));
                printf("input your nu\n");
                scanf("%d", &(new->data));
                if(new->data == 0){
                        printf("0 quit\n");
                        return head;
                }
                head = insertBehind(head,new);
        }
}
int main()
{
        struct Test *head = NULL;
        head = creatLink(head);
        printLink(head);
		return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值