学习嵌入式第十九天

文章目录

链表(续上)

1.单向链表

6.链表的查找

在链表中找到指定的第一个元素

  • 遍历链表节点,判断是否为要找的节点
  • 符合条件的返回该节点地址
  • 如果遍历结束没有找到元素,返回空
c 复制代码
linknode *search_linklist(linknode *phead, datatype tmpdata){

    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;

    while(ptmpnode != NULL){

        if(ptmpnode->data == tmpdata){

            return ptmpnode;
        }
        else{

            ptmpnode = ptmpnode->pnext;
        }
    }
    return NULL;

}
7.链表的修改

将链表节点的旧元素改为新元素

c 复制代码
void change_linklist(linknode *phead, datatype tmpdata,datatype overdata){

    linknode *ptmpnode = NULL;

    ptmpnode = phead->pnext;

    while(ptmpnode != NULL){

        if(ptmpnode->data == tmpdata){
            
            ptmpnode->data = overdata;
        }
            ptmpnode = ptmpnode->pnext;
    }
    return;

}
8.链表的尾插法
  • 申请节点空间,将节点中地址赋值为NULL,将数据存放到节点
  • 找到最后一个节点
  • 将最后一个节点的pnext赋值为新申请节点的地址
c 复制代码
void insert_tail_linklist(linknode *phead,datatype tmpdata){

    linknode *ptmpnode = NULL;
    linknode *pnewnode = NULL;

    pnewnode = malloc(sizeof(linknode));
    pnewnode->data = tmpdata;
    pnewnode->pnext = NULL;
   
    ptmpnode = phead;
    
    while(ptmpnode->pnext != NULL){

        ptmpnode = ptmpnode->pnext;
    }
    
    ptmpnode->pnext = pnewnode; 
    return;
}
9.链表的销毁

将链表节点全部释放

  • 定义两个指针ptmpnode和pprenode指向头节点
  • ptmpnode指向ptmpnode->pnext
  • 释放掉pfreenode指向的节点
  • 将pfreenode指向ptmpnode指向的空间
C 复制代码
int destroy_linklist(linknode **pphead){

    linknode *pfreenode = NULL;
    linknode *ptmpnode = NULL;

    ptmpnode = *pphead;
    pfreenode = *pphead;
    while(ptmpnode != NULL){

        ptmpnode = ptmpnode->pnext;
        free(pfreenode);
        pfreenode = ptmpnode;
    }
    *pphead = NULL;

    return 0;
}
10.查找链表中间节点
  • 快指针pfast每次走两步,慢指针pslow每次走一步
  • 快指针走到末尾的时候,慢指针刚好走到中间
c 复制代码
linknode *find_minnode_linklist(linknode *phead){

    linknode *pfast = NULL;
    linknode *pslow = NULL;

    pfast = phead->pnext;
    pslow = phead->pnext;
    while(pfast != NULL){

        pfast = pfast->pnext;
        if(pfast == NULL){
            break;
        }
        pfast = pfast->pnext;
        if(pfast == NULL){
            break;
        }
        pslow = pslow->pnext;
    }
    return pslow;
}
11.查找链表倒数第k个节点
  • 快指针先走k步
  • 慢指针和快指针每次走一步
  • 快指针到达末尾的时候,慢指针指向倒数第k个元素
c 复制代码
linknode *find_knode_linklist(linknode *phead,int k){

    int i = 0;
    linknode *pfast = NULL;
    linknode *pslow = NULL;
    
    pfast = phead->pnext;
    while(i < k && pfast != NULL){

        pfast = pfast->pnext;
        i++;
    }
    if(NULL == pfast){

        return NULL;
    }
    pslow = phead->pnext;
    while(pfast != NULL){

        pfast = pfast->pnext;
        pslow = pslow->pnext;
    }
    return pslow;
}
12.不知道头节点地址删除链表中间节点
  • 将指针指向下一个节点的值覆盖当前节点的值
  • 删除下一节点
c 复制代码
void delete_linknode(linknode *ptmpnode){

    linknode *pnextnode = NULL;

    pnextnode = ptmpnode->pnext;
    ptmpnode->data = pnextnode->data;
    ptmpnode->pnext = pnextnode->pnext;
    free(pnextnode);
    pnextnode = NULL;
}
13.链表倒置
  • 将原链表从头结点处断开
  • 将所有元素按照头插法插入
c 复制代码
void reverse_linklist(linknode *phead){

    linknode *ptmpnode = NULL;
    linknode *pinsertnode = NULL;

    ptmpnode = phead->pnext;
    phead->pnext = NULL;

    while(ptmpnode != NULL){

        pinsertnode = ptmpnode;
        ptmpnode = ptmpnode->pnext;
        pinsertnode->pnext = phead->pnext;
        phead->pnext = pinsertnode;

    } 
    return;
}
14.链表的排序
1.冒泡排序
  • 定义两个指针ptmpnode1,ptmpnode2用作比较,定义一个指针pend记录每轮排序的最后节点
  • 指针循环向后走,直到ptmpnode2为NULL,即等于pend,循环停止
  • pend赋值为ptmpnode1的节点地址,下一轮就可以少比一次
  • 循环将所有大的元素找到,剩余一个最小元素
c 复制代码
void bubblesort_linklist(linknode *phead){

    linknode *ptmpnode = NULL;
    linknode *pprenode = NULL;
    linknode *pend = NULL;
    int tmpdata = 0;
    int flag = 1;

    if(phead->pnext == NULL || phead->pnext->pnext == NULL){

        return;
    }
    
    while(flag){

        flag = 0;
        pprenode = phead->pnext;
        ptmpnode = phead->pnext->pnext;

        while(ptmpnode != pend){

            if(pprenode->data > ptmpnode->data){

                tmpdata = pprenode->data;
                pprenode->data = ptmpnode->data;
                ptmpnode->data = tmpdata;
                flag = 1;
            }
            pprenode = ptmpnode;
            ptmpnode = ptmpnode->pnext;
        }
        pend = pprenode;
    }
    return;
}   
2.选择排序
  • pswapnode指向要交换的节点
  • pminnode假设的最小值
  • ptmpnode和后续节点比较
C 复制代码
void selectsort_linklist(linknode *phead){

    linknode *ptmpnode = NULL;
    linknode *pswapnode = NULL;
    linknode *pminnode = NULL;
    datatype tmpdata;

    if(phead->pnext == NULL || phead->pnext->pnext == NULL){

        return;
    }
    
    pswapnode = phead->pnext;
    while(pswapnode->pnext != NULL){

        pminnode = pswapnode;
        ptmpnode = pswapnode->pnext;

        while(ptmpnode != NULL){

            if(ptmpnode->data < pminnode->data){

                pminnode = ptmpnode;
            }
            ptmpnode = ptmpnode->pnext;
        }
        if(pminnode != pswapnode){

            tmpdata = pswapnode->data;
            pswapnode->data = pminnode->data;
            pminnode->data = tmpdata;
        }
        pswapnode = pswapnode->pnext;
    }
    return;
}
15.判断链表是否有环
  1. 判断链表是否有环
    • 定义两个指针:快指针(每次走两步)和慢指针(每次走一步)
    • 快指针-慢指针 == 环长,快指针和慢指针相等即为链表有环
  2. 计算环的环长
    • 定义一个指针从环相遇点开始走一圈,直到走到该节点为止
    • 每走一个节点计数,最终得到环长
  3. 找到环入口的位置
    • 起点到环入口的距离 = 相遇点到环入口的距离 + (n-1) * 环长
    • 定义一个指针从相遇点开始每次走一步,定义一个指针从开头每次走一步
    • 两个指针相遇的位置几位环入口位置
c 复制代码
int circle_linklist(linknode *phead,int *pis_circle,int *pcirlen,linknode **ppnode){

    linknode *pfast = NULL;
    linknode *pslow = NULL;
    linknode *ptmpnode = NULL;
    linknode *pstartnode = NULL;
    int cnt = 1;
/*判断是否有环*/
    pfast = phead->pnext;
    pslow = phead->pnext;
    while(1){

        pfast = pfast->pnext;
        if(NULL == pfast){

            break;
        }
        pfast = pfast->pnext;
        if(NULL == pfast){

            break;
        }
        pslow = pslow->pnext;
        if(pfast == pslow){

            break;
        }
    }
    if(NULL == pfast){

        *pis_circle = 0;
        return 0;
    }
    else{

        *pis_circle = 1;
    }

    /*计算环长*/
    ptmpnode = pslow->pnext;
    while(ptmpnode != pslow){

        cnt++;
        ptmpnode = ptmpnode->pnext;
    }
    *pcirlen = cnt;
    /*找到环的起始节点*/
    pstartnode = phead->pnext;
    ptmpnode = pslow;
    while(pstartnode != ptmpnode){

        pstartnode = pstartnode->pnext;
        ptmpnode = ptmpnode->pnext;
    }
    *ppnode = ptmpnode;

    return 0;
}

2.双向链表

1.节点定义
c 复制代码
typedef int datatype;

typedef struct node{
    
    datatype data;
    struct node *ppre;
    struct node *pnext;
}linknode;
2.创建节点

参考单向链表创建

  • 申请节点空间
  • 对pnext和ppre赋值为NULL
  • 返回空白节点地址
c 复制代码
linknode *create_empty_linklist(void){
    
    linknode *ptmpnode = NULL;
    
    ptmpnode = alloc(sizeof(linknode));
    if(NULL == ptmpnode){
        
        perror("fail to malloc");
        return NULL;
    }
    ptmpnode->ppre = NULL;
    ptmpnode->pnext = NULL;
    
    return ptmpnode;
}
3.链表的头插法
  • 申请节点
  • 存放数据
  • pnext赋值为phead->pnext
  • ppre赋值为phead的地址
  • phead->pnext赋值为新申请节点地址
  • 如果有后一个节点,需要让后一个节点的ppre指向该节点

习题

实现双向链表的基本操作

  1. 创建

    代码实现:

    c 复制代码
    linknode *create_empty_linklist(void){
    
        linknode *ptmpnode = NULL;
    
        ptmpnode = malloc(sizeof(linknode));
    
        if(ptmpnode == NULL){
    
            perror("fail to malloc");
            return NULL;
        }
        ptmpnode->ppre = NULL;
        ptmpnode->pnext = NULL;
    
        return ptmpnode; 
    }
  2. 销毁

    代码实现:

    C 复制代码
    int destory_linklist(linknode **pphead){
    
        linknode *ptmpnode = NULL;
        linknode *pnextnode = NULL;
    
        ptmpnode = *pphead;
        pnextnode = *pphead;
    
        while(ptmpnode != NULL){
    
            pnextnode = pnextnode->pnext;
            free(ptmpnode);
            ptmpnode = pnextnode;
        }
        *pphead = NULL;
    }
  3. 头插法

    代码实现:

    c 复制代码
    int insert_head_linklist(linknode *phead,datatype tmpdata){
    
        linknode *ptmpnode = NULL;
    
        ptmpnode = malloc(sizeof(linknode));
    
        if(ptmpnode == NULL){
    
            perror("fail to malloc");
            return -1;
        }
        ptmpnode->data = tmpdata;
    
        ptmpnode->pnext = phead->pnext;
        phead->pnext = ptmpnode;
        ptmpnode->ppre = phead;
        if(ptmpnode->pnext != NULL){
    
            ptmpnode->pnext->ppre = ptmpnode;
        }
        return 0;
    }
  4. 遍历

    代码实现:

    c 复制代码
    int show_linklist(linknode *phead){
        linknode *ptmpnode = NULL;
    
        ptmpnode = phead->pnext;
        while(ptmpnode != NULL){
    
            printf("%d ",ptmpnode->data);
            ptmpnode = ptmpnode->pnext;
        }
        printf("\n");
    }
  5. 查找

    代码实现:

    C 复制代码
    linknode *find_linklist(linknode *phead,datatype tmpdata){
    
        linknode *ptmpnode = NULL;
    
        ptmpnode = phead->pnext;
    
        while(ptmpnode != NULL){
    
            if(ptmpnode->data == tmpdata){
    
                printf("%d ",ptmpnode->data);
            }
            ptmpnode = ptmpnode->pnext;
        }
        printf("\n");
        return NULL;
    }
  6. 修改

    代码实现:

    c 复制代码
    int update_linklist(linknode *phead, datatype olddata, datatype
    newdata){
    
        linknode *ptmpnode = NULL;
    
        ptmpnode = phead->pnext;
    
        while(ptmpnode != NULL){
    
            if(ptmpnode->data == olddata){
    
                ptmpnode->data = newdata;
                
            }
            ptmpnode = ptmpnode->pnext;
        }
        return 0;
    }
  7. 删除

    代码实现:

    c 复制代码
    int delete_linklist(linknode *phead, datatype tmpdata){
    
        linknode *ptmpnode = NULL;
        linknode *pprenode = NULL;
    
        ptmpnode = phead->pnext;
        pprenode = phead;
    
        while(ptmpnode != NULL){
    
            if(ptmpnode->data == tmpdata){
    
                pprenode->pnext = ptmpnode->pnext;
                free(ptmpnode);
                pprenode->pnext->ppre = pprenode;
                ptmpnode = pprenode->pnext;
            }
            else{
    
                pprenode = ptmpnode;
                ptmpnode = ptmpnode->pnext;
            }
        }
        return 0;
相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习
im_AMBER6 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J6 天前
从“Hello World“ 开始 C++
c语言·c++·学习