数据结构(三)循环链表 约瑟夫环

news2025/1/21 0:52:56

文章目录

  • 一、循环链表
    • (一)概念
    • (二)示意图
    • (三)操作
      • 1. 创建循环链表
        • (1)函数声明
        • (2)注意点
        • (3)代码实现
      • 2. 插入(头插,尾插,任意位置插入)
        • (1)头插
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (2)尾插
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (3)任意位置插入
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
      • 3. 删除(头删,尾删,任意位置删除)
        • (1)头删
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (2)尾删
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (3)任意位置删除
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
      • 4. 修改
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 5. 查询
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 6. 清空和销毁
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 7. 打印链表(方便查看实验现象)
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 8. 排序(以正序排序为例)
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 9.剔重
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
    • (四)应用:实现约瑟夫环
      • 1.问题描述
      • 2. 问题分析
      • 3. 代码实现
      • 4. 使用前面的循环链表实现
  • 二、代码源码已上传资源

一、循环链表

(一)概念

操作和单向链表的操作基本一样
只是判断链表结束的条件不同

循环链表又分为有头循环链表和无头循环链表,其中无头结点的循环链表相对更常见些,因此下文以实现无头循环链表为例。

(二)示意图

在这里插入图片描述

(三)操作

结构体定义:

//数据元素结构体
typedef struct circle_node
{
    int data;
    struct circle_node *next;
}nd_t;

//数据对象结构体
typedef struct circle_list
{
    nd_t *phead; //指向头节点
    //还可以添加其他成员
}list_t;

1. 创建循环链表

(1)函数声明

int create_list(list_t **my_list);

创建循环链表的第一个节点,
第一个节点的next指向它自己
将第一个节点的堆区地址传给main函数中的指针

(2)注意点
  1. 入参不能为空
  2. 因为需要将申请的第一个节点的地址写入main函数中的指针变量中,因此必须传入二级指针
  3. 申请内存空间后检查是否申请成功
(3)代码实现
int create_list(list_t **my_list){
    if(NULL==my_list){
        return -1;
    }
    *my_list=(list_t *)malloc(sizeof(list_t));
    if(NULL==*my_list){
        return -1;
    }
    (*my_list)->phead=NULL;
    return 0;
}

2. 插入(头插,尾插,任意位置插入)

(1)头插
① 函数声明

int insert_list_by_head(list_t *my_list,int num);

创建新节点
找到尾节点,将尾节点的next指向新的节点
新节点的next指向首节点
*phead指向pnew

② 注意点
  1. 入参不能为NULL
  2. 头插需要更改main函数中phead指针的值,因此需要传二级指针
  3. 需要保证链表中至少有一个节点,无头链表中只要phead不为NULL,就说明至少有一个节点
③ 代码实现
int insert_list_by_head(list_t *my_list,int num){
    //入参不合理
    if(NULL==my_list)
        return -1;
    //创建新节点
    nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));
    if(NULL==pnew)
        return -1;
    pnew->data=num;
    //插入首节点
    if(NULL==my_list->phead){
        my_list->phead=pnew;
        pnew->next=pnew;
        return 0;
    }
    //如果插入的不是第一个节点
    //先找到尾节点
    nd_t *ptemp=my_list->phead;
    while(ptemp->next!=my_list->phead)
    {
        ptemp=ptemp->next;
    }
    //插入
    ptemp->next=pnew;
    pnew->next=my_list->phead;
    my_list->phead=pnew;
    return 0;
}
(2)尾插
① 函数声明

int insert_list_by_tail(list_t *my_list,int num);

创建新节点
找到尾节点,将尾节点的next指向新的节点
新节点的next指向首节点

② 注意点
  1. 头插和尾插的区别仅在于是否需要修改main函数中的指针变量
③ 代码实现
int insert_list_by_tail(list_t *my_list,int num){
    if(NULL==my_list)
        return -1;
    //创建新节点
    nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));
    if(NULL==pnew)
        return -1;
    pnew->data=num;
    //插入首节点
    if(NULL==my_list->phead){
        my_list->phead=pnew;
        pnew->next=pnew;
        return 0;
    }
    //找到尾节点
    nd_t *ptemp=my_list->phead;
    while(ptemp->next!=my_list->phead)
    {
        ptemp=ptemp->next;
    }
    //插入
    ptemp->next=pnew;
    pnew->next=my_list->phead;
    return 0;
}
(3)任意位置插入
① 函数声明

int insert_list_by_pos(list_t *my_list,int pos,int num);

找到要插入的位置的前一个节点
创建新节点
插入节点

② 注意点
  1. 不支持插入在第一个位置
  2. 如果插入的前一个位置在最后一个可以,但是在第一个就不合理了
③ 代码实现
int insert_list_by_pos(list_t *my_list,int pos,int num){
    if(NULL==my_list)
        return -1;
    if(pos<0)
        return -1;
    //找到要插入的节点的前一位
    nd_t *ptemp=my_list->phead;
    int i=0;//记录ptemp移动了几步
    while(ptemp->next!=my_list->phead){
        if(i==pos-1) break; 
        ptemp=ptemp->next;
        i++;
    }
    //如果已经到尾节点了还没移动到pos位置就说明位置不合理
    if(i<pos-1){
        printf("位置不合理\n");
        return -1;
    }
    //创建新节点
    nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));
    if(NULL==pnew)
        return -1;
    pnew->data=num;
    //插入第一个节点
    if(NULL==my_list->phead){
        my_list->phead=pnew;
        pnew->next=pnew;
        return 0;
    }
    //插入到头节点
    if(0==pos){
        nd_t *ptail=my_list->phead;
        while(ptail->next!=my_list->phead)
            ptail=ptail->next;
        ptail->next=pnew;
        pnew->next=my_list->phead;
        my_list->phead=pnew;
        return 0;
    }
    //插入节点
    pnew->next=ptemp->next;
    ptemp->next=pnew;

    return 0;
}

3. 删除(头删,尾删,任意位置删除)

(1)头删
① 函数声明

delete_list_by_head(list_t *my_list);

找到尾节点
尾节点的next置成*phead->next
*phead=*phead->next
free(pdef)

② 注意点
  1. 需要传入二级指针
  2. 当表中只有一个节点时,进行删除操作时相当于将表销毁了。
③ 代码实现
int delete_list_by_head(list_t *my_list){
    //传参为空或者表为空
    if(NULL==my_list||NULL==my_list->phead)
        return -1;
    //只有一个节点
    if(my_list->phead->next==my_list->phead){
        free(my_list->phead);
        my_list->phead=NULL;
        printf("表已清空\n");
        return 0;
    }
    //多个节点
    //找到尾节点
    nd_t *ptemp=my_list->phead->next;
    while(ptemp->next!=my_list->phead)
    {
        ptemp=ptemp->next;
    }
    //头删
    nd_t *pdel=my_list->phead;
    my_list->phead=my_list->phead->next;
    ptemp->next=my_list->phead;
    free(pdel);
    pdel=NULL;
    return 0;
}
(2)尾删
① 函数声明

int delete_list_by_tail(list_t *my_list);

找到尾节点的前一节点,
尾删操作

② 注意点
  1. 需要传入二级指针
  2. 当表中只有一个节点时,进行删除操作时相当于将表销毁了。
③ 代码实现
int delete_list_by_tail(list_t *my_list){
    //传参为空或者表为空
    if(NULL==my_list||NULL==my_list->phead)
        return -1;
    //只有一个节点
    if(my_list->phead->next==my_list->phead){
        free(my_list->phead);
        my_list->phead=NULL;
        printf("表已清空\n");
        return 0;
    }
    //多个节点
    //找到尾节点的前一个节点
    nd_t *ptemp=my_list->phead->next;
    while(ptemp->next->next!=my_list->phead)
    {
        ptemp=ptemp->next;
    }
    //尾删
    nd_t *pdel=ptemp->next;
    ptemp->next=my_list->phead;
    free(pdel);
    pdel=NULL;
    return 0;
}
(3)任意位置删除
① 函数声明

int delete_list_by_pos(list_t *my_list,int pos);

② 注意点
  1. 链表中至少有一个节点
  2. 如果只有一个节点时要删除第0个位置可以成功,此时链表销毁;其他位置均为不合理
  3. 如果多个节点时,需要区分是不是要删除头节点
  4. ptemp是要删除的节点的前一个节点,它不能是尾节点
③ 代码实现
int delete_list_by_pos(list_t *my_list,int pos){
    //传参为空或者表为空
    if(NULL==my_list||NULL==my_list->phead)
        return -1;
    if(0>pos){
        return -1;
    }
    //如果链表中只有一个节点
    if(my_list->phead->next==my_list->phead){
        //删除第一个位置的节点
        if(0==pos){
            free(my_list->phead);
            my_list->phead=NULL;
            return 0;
        }
        //删除其他位置节点,均是位置不合理
        printf("位置不合理\n");
        return -1;
    }
    //链表有多个节点
    nd_t *pdel=my_list->phead;
    //删除第一个位置的节点
    //找到尾节点
    nd_t *ptemp=my_list->phead;
    while(ptemp->next!=my_list->phead)
    {
        ptemp=ptemp->next;
    }
    if(0==pos){
        my_list->phead=my_list->phead->next;
        ptemp->next=my_list->phead;
        free(pdel);
        pdel=NULL;
        return 0;
    }
    //删除其他位置节点
    //找到要删除的节点的前一个节点
    ptemp=my_list->phead;
    for(int i=0;i<pos-1;i++){
        //要删除的节点的前一个节点不能是尾节点
        if(ptemp->next->next==my_list->phead){
            printf("删除位置不合理\n");
            return -1;
        }
        ptemp=ptemp->next;
    }
    pdel=ptemp->next;
    ptemp->next=pdel->next;
    free(pdel);
    pdel=NULL;
    return 0;
}

4. 修改

(1)函数定义

int modify_list_by_pos(list_t *my_list,int pos,int num);

遍历链表找到第pos个位置

(2)注意点
  1. 如果已经到达尾节点就不能再继续向下遍历修改
(3)代码实现
int modify_list_by_pos(list_t *my_list,int pos,int num){
    //至少有一个节点
    if(NULL==my_list||NULL==my_list->phead)
        return -1;
    if(0>pos){
        return -1;
    }
    //找到第pos个位置
    nd_t *ptemp=my_list->phead;
    for(int i=0;i<pos;i++){
        if(ptemp->next==my_list->phead){
            printf("位置不合理\n");
            return -1;
        }
        ptemp=ptemp->next;
    }
    ptemp->data=num;
    return 0;
}

5. 查询

(1)函数定义

int search_list_by_pos(list_t *my_list,int pos,int *num);

找到第pos个位置
读取数据域数据

(2)注意点
  1. 查询和修改的唯一区别是对数据的处理,修改是将新的数据写到第pos尾的数据域;修改是将pos位的数据域写到num中
  2. 循环结束条件与修改和删除一样
(3)代码实现
int search_list_by_pos(list_t *my_list,int pos,int *num){
    //至少有一个节点
    if(NULL==my_list||NULL==my_list->phead||NULL==num)
        return -1;
    if(0>pos){
        return -1;
    }
    //找到第pos个位置
    nd_t *ptemp=my_list->phead;
    for(int i=0;i<pos;i++){
        if(ptemp->next==my_list->phead){
            printf("位置不合理\n");
            return -1;
        }
        ptemp=ptemp->next;
    }
    *num=ptemp->data;
    return 0;
}

6. 清空和销毁

(1)函数定义

int clean_list(list_t *my_list);
int destory_list(list_t **my_list);

先判断是不是只有一个节点
采用尾删(使用头删的话还要一直修改main函数中的指针变量的值)

(2)注意点
  1. 使用二级指针
  2. 入参不能为空
(3)代码实现
int clean_list(list_t *my_list){
    if(NULL==my_list){
        return -1;
    }
    //不止一个节点
    //采用头删,先找到尾节点前一个节点
    while(my_list->phead!=NULL)
    {
        delete_list_by_head(my_list);
    }
    return 0;
}
int destory_list(list_t **my_list){
    if(NULL==my_list||NULL==*my_list){
        return -1;
    }
    clean_list(*my_list);
    //此时只有一个节点了
    free(*my_list);
    *my_list=NULL;
    return 0;
}

7. 打印链表(方便查看实验现象)

(1)函数定义

int print_list(list_t *my_list);

先打印出第一个节点,
遍历链表,直到ptemp->next==phead时结束

(2)注意点
  1. 在无头链表中phead为NULL,则说明表为空。phead->next==NULL,说明没有第二个节点。
(3)代码实现
int print_list(list_t *my_list){
    if(NULL==my_list)
        return -1;
    nd_t *ptemp=my_list->phead->next;
    //打印头节点
    printf("%d ",my_list->phead->data);
    //当ptemp==mylist->phead时,说明回到了开头
    while(ptemp!=my_list->phead){
        printf("%d ",ptemp->data);
        ptemp=ptemp->next;
    }
    putchar(10);
    return 0;
}

8. 排序(以正序排序为例)

(1)函数定义

int sort_list(list_t *my_list);;

选择排序思路

(2)注意点
  1. 外层循环可以不比较最后一个元素
(3)代码实现
int sort_list(list_t *my_list){
    if(NULL==my_list||NULL==my_list->phead){
        return -1;
    }
    nd_t *p=my_list->phead;
    nd_t *q=NULL;
    while(p->next!=my_list->phead){
        q=p->next;
        while(q!=my_list->phead){
            if(p->data>q->data){
                int temp=p->data;
                p->data=q->data;
                q->data=temp;
            }
            q=q->next;
        }
        p=p->next;
    }
    return 0;
}

9.剔重

(1)函数定义

int dedup_list(list_t *my_list);

动静指针配合
选择排序思路

(2)注意点
  1. 此时外层循环使用p->next!=phead或者p!=phead均可,循环链表此刻不会报段错误,但是用第一种效率会相对略高
(3)代码实现
int dedup_list(list_t *my_list){
    //至少有一个元素
    if(NULL==my_list||NULL==my_list->phead){
        return -1;
    }
    nd_t *p=my_list->phead;
    nd_t *q=NULL;
    nd_t *m=NULL;
    while(p->next!=my_list->phead){
        m=p;
        q=p->next;
        while(q!=my_list->phead){
            if(p->data==q->data){
                m->next=q->next;
                free(q);
                q=m->next;
            }else{
                m=q;
                q=q->next;
            }
        }
        p=p->next;
    }
}

(四)应用:实现约瑟夫环

1.问题描述

有一位叫约瑟夫的将军,在一次战斗中,连同手下的士兵一起被俘虏了。手下的士兵都非常爱国,宁死不投降,约瑟夫将军想了个办法:
让大家站成一圈,开始数数,从1开始数,数到7的人就自杀,
下一个人重新从1开始数,数到7再自杀,依次类推
直到只剩下一个人为止,最终剩下的就是约瑟夫将军,
然后他不想死,他投降了。这种“圈”,我们称之为“约瑟夫环”

要求:编写代码,模拟约瑟夫环淘汰人的过程,
命令行输入 ./a.out 总人数 数到几自杀 (总人数>1 数到几自杀>1 )
要求程序输出:
第x次 淘汰的是y号
以及最终剩下的是几号
如:输入 ./a.out 5 3 则程序输出
第1次 淘汰的是3号
第2次 淘汰的是1号
第3次 淘汰的是5号
第4次 淘汰的是2号
最后剩下的是 4 号

2. 问题分析

首先需要检查参数的合理性,参数都是以字符串形式保存的,需要转换成int型数据;
无头链表创建链表时就是创建第一个节点,即编号为1的人,之后依次开始创建节点

3. 代码实现

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

typedef struct _Node{
    int data;
    struct _Node *next;
}node_t;

node_t *create_circle(int num){
    //创建第一个节点
    node_t *phead=(node_t *)malloc(sizeof(node_t));
    if(NULL==phead) return NULL;
    phead->data=1;
    phead->next=phead;
    //创建剩余节点
    node_t *pnew=NULL;
    node_t *ptemp=phead;
    for(int i=1;i<num;i++){
        pnew=(node_t *)malloc(sizeof(node_t));
        pnew->data=i+1;
        if(NULL==pnew) return NULL;
        //找到尾节点
        while (ptemp->next!=phead)
            ptemp=ptemp->next;
        pnew->next=ptemp->next;
        ptemp->next=pnew;
    }
    return phead;
}

int print_circle(node_t *phead){
    if(NULL==phead) return -1;
    node_t *ptemp=phead;
    while(ptemp->next!=phead){
        printf("%d ",ptemp->data);
        ptemp=ptemp->next;
    }
    printf("%d ",ptemp->data);
    putchar(10);
    return 0;
}

int del_circle(node_t *phead,int count){
    if(NULL==phead) return -1;
    int c=1;
    int sum=0;
    node_t *pprev=NULL;
    while(phead->next!=phead){
        if(c==count){
            sum++;
            c=1;
            printf("第%d次淘汰%d号\n",sum,phead->data);
            pprev->next=phead->next;
            free(phead);
            phead=pprev->next;
            continue;
        }
        c++;
        pprev=phead;
        phead=phead->next;
    }
    printf("第%d号存活\n",phead->data);
    return 0;
}

int main(int argc, char const *argv[])
{
    if (argc!=3){
        printf("./a/out 总人数 数到几\n");
        return -1;
    }
    int sum=atoi(argv[1]); //人数 
    int num=atoi(argv[2]); //数到几
    node_t *my_list=NULL;
    my_list=create_circle(sum);
    print_circle(my_list);
    del_circle(my_list,num);
    return 0;
}

4. 使用前面的循环链表实现

main.c文件:

#include "circle_list.h"

int del(nd_t *phead,int n);
int main(int argc, char const *argv[])
{
    if(3 != argc)
    {
        printf("参数不合理\n");
        return -1;
    }
    int num=atoi(argv[1]); //保存个数
    int n=atoi(argv[2]);//数到几
    if(num<=0)
    {
        printf("人数应当大于0\n");
        return-1;
    }
    list_t *my_list=NULL;
    //第一个人及其编号
    create_list(&my_list);
    //后面的人
    for(int i=1;i<=num;i++){
        if(insert_list_by_tail(my_list,i)){
            printf("插入失败\n");
            return -1;
        }
    }
    print_list(my_list);  
    del(my_list->phead,n);
    return 0;
}

int del(nd_t *phead,int n)
{
    if(NULL==phead)
    {
        printf("传参错误\n");
        return -1;
    }
    if(0>=n)
    {
        printf("传参错误,n应当大于0\n");
        return -1;
    }
    int index=0;
    nd_t *pptemp=NULL;

    while(phead->next!=phead)
    {
        for(int i=0;i<n-1;i++) //phead默认移到下一位了,故只需要再移动n-1次
        {
            pptemp=phead;
            phead=phead->next;
        }
        //此时phead是需要删除的节点,执行删除操作
        pptemp->next=phead->next; 
        printf("第%d次删除%d\n",index+1,phead->data);
        free(phead);
        //删除完成后pead等于后一个节点
        phead=pptemp->next;
        index++;
    }
    printf("%d存活\n",phead->data);
    free(phead);
    phead=NULL;
    return 0;
}

二、代码源码已上传资源

链接:
C语言实现循环链表源码链接
C语言实现约瑟夫环源码链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1719414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据分享】中国劳动统计年鉴(1991-2023)

大家好&#xff01;今天我要向大家介绍一份重要的中国劳动统计数据资源——《中国劳动统计年鉴》。这份年鉴涵盖了从1991年到2023年中国劳动统计全面数据&#xff0c;并提供限时免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 1991年以来&#xff0c;中…

玄机平台应急响应—Linux日志分析

1、前言 啥是日志呢&#xff0c;日志就是字面意思&#xff0c;用来记录你干了啥事情。日志大体可以分为网站日志和系统日志&#xff0c;网站日志呢就是记录哪个用户在哪里什么时候干了啥事&#xff0c;以及其它的与网站相关的事情。系统日志呢&#xff0c;就是记录你的电脑系统…

飞腾+FPGA多U多串全国产工控主机

飞腾多U多串工控主机基于国产化飞腾高性能8核D2000处理器平台的国产自主可控解决方案&#xff0c;搭载国产化固件,支持UOS、银河麒麟等国产操作系统&#xff0c;满足金融系统安全运算需求&#xff0c;实现从硬件、操作系统到应用的完全国产、自主、可控&#xff0c;是国产金融信…

【计算机毕设】基于SpringBoot的房产销售系统设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 随着房地产市场的发展和互联网技术的进步&#xff0c;传统的房产销售模式逐渐向线上转移。设计并实现一个基于Spring Boot的房产销售系统&#xff0…

用HAL库改写江科大的stm32入门-6-3 PWM驱动LED呼吸灯

接线图&#xff1a; 2 :实验目的&#xff1a; 利用pwm实现呼吸灯。 关键PWM定时器设置&#xff1a; 代码部分&#xff1a; int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*…

神经网络---卷积神经网络CNN

一、从前馈神经网络到CNN 前馈神经网络&#xff08;Feedforward Neural Networks&#xff09;是最基础的神经网络模型&#xff0c;也被称为多层感知机&#xff08;MLP&#xff09;。 它由多个神经元组成&#xff0c;每个神经元与前一层的所有神经元相连&#xff0c;形成一个“…

【C语言】基于C语言实现的贪吃蛇游戏

【C语言】基于C语言实现的贪吃蛇游戏 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C语言学习之路 文章目录 【C语言】基于C语言实现的贪吃蛇游戏前言一.最终实现效果一.Win32 API介绍1.1Win32 API1.2控制台程序1.3控制台屏幕上的坐标COORD…

【kubernetes】探索k8s集群的存储卷、pvc和pv

目录 一、emptyDir存储卷 1.1 特点 1.2 用途 1.3部署 二、hostPath存储卷 2.1部署 2.1.1在 node01 节点上创建挂载目录 2.1.2在 node02 节点上创建挂载目录 2.1.3创建 Pod 资源 2.1.4访问测试 2.2 特点 2.3 用途 三、nfs共享存储卷 3.1特点 3.2用途 3.3部署 …

放开了去的 ulimit

放开了去的 ulimit 放开了去的 ulimitulimit简介临时修改打开文件数目永久修改系统总打开句柄限制更多信息 放开了去的 ulimit ulimit简介 对于高并发或者频繁读写文件的应用程序而言&#xff0c;有时可能需要修改系统能够打开的最多文件句柄数&#xff0c;否则就可能会出现t…

【网络原理】HTTP|认识请求“报头“|Host|Content-Length|Content-Type|UA|Referer|Cookie

目录 认识请求"报头"(header) Host Content-Length Content-Type User-Agent(简称UA) Referer &#x1f4a1;Cookie&#xff08;最重要的一个header&#xff0c;开发&面试高频问题&#xff09; 1.Cookie是啥&#xff1f; 2.Cookie怎么存的&#xff1f; …

系统架构设计师【第8章】: 系统质量属性与架构评估 (核心总结)

文章目录 8.1 软件系统质量属性8.1.1 质量属性概念8.1.2 面向架构评估的质量属性8.1.3 质量属性场景描述 8.2 系统架构评估8.2.1 系统架构评估中的重要概念8.2.2 系统架构评估方法 8.3 ATAM方法架构评估实践8.3.1 阶段1—演示&#xff08;Presentation&#xff09;8.3…

卷积网络迁移学习:实现思想与TensorFlow实践

摘要&#xff1a;迁移学习是一种利用已有知识来改善新任务学习性能的方法。 在深度学习中&#xff0c;迁移学习通过迁移卷积网络&#xff08;CNN&#xff09;的预训练权重&#xff0c;实现了在新领域或任务上的高效学习。 下面我将详细介绍迁移学习的概念、实现思想&#xff0c…

SpringMVC响应数据 View

1.如何封装数据返回页面 使用ModelAndView&#xff1a; ModelAndView modelAndView new ModelAndView() modelAndView.addObject() 方法封装数据 使用Controller中内置Model对象 model&#xff1a; model.addAttribute("name","zz"); 2.跳转的方式…

el-date-picker的使用,及解决切换type时面板样式错乱问题

这里选择器的类型可以选择日月年和时间范围&#xff0c;根据类型不同&#xff0c;el-date-picker的面板也展示不同&#xff0c;但是会出现el-date-picker错位&#xff0c;或者面板位置和层级等问题。 源代码&#xff1a; <el-selectv-model"dateType"placeholder&…

【PTA】7-4 朋友圈(C++ * 并查集思想)代码实现 一点反思

题目如下&#xff1a; AC代码如下&#xff08;参考PTA 7-2 朋友圈&#xff08;25 分&#xff09;_处理微信消息pta-CSDN博客&#xff09; #include<bits/stdc.h> using namespace std; #define sz 30005 typedef struct node{int rk, fa; }Node; Node tree[sz]; void In…

HTTPS 原理技术

HTTPS原理技术 背景简介原理总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本文内容并非完全原创&am…

Ubuntu安装GCC编译器

GCC编译器安装 GCC编译器安装切换软件源(换成国内的服务器)1 、创建一个文本文档并命名为“sources.list”2 、复制软件源列表清华源:阿里源:3 、把修改之后的.list 文件覆盖原有的文件4 、更新软件列表5 、安装6 、检查是否安装成功7、GCC 编译器:GCC编译器安装 这里演示…

二维数组传参时不用二级指针接收

先放结论&#xff1a; 1. 二维数组数组名指向的类型是 int [x] 类型&#xff0c;int** 指针指向类型是 int* &#xff0c;如果用二级指针接收会导致访问错误&#xff0c;因为 int [x] 类型和 int* 类型不同。 2. 指向什么类型的指针1就按照该类型的字节数1移动。 最近在学…

高并发项目-分布式Session解决方案

分布式Session解决方案 1.保存Session&#xff0c;进入商品列表页面 1.保存Session 1.编写工具类 1.MD5Util.java package com.sxs.seckill.utils;import org.apache.commons.codec.digest.DigestUtils;/*** Description: MD5加密工具类** Author sun* Create 2024/5/5 14…

uni-app实现页面通信EventChannel

uni-app实现页面通信EventChannel 之前使用了EventBus的方法实现不同页面组件之间的一个通信&#xff0c;在uni-app中&#xff0c;我们也可以使用uni-app API —— uni.navigateTo来实现页面间的通信。注&#xff1a;2.8.9 支持页面间事件通信通道。 1. 向被打开页面传送数据…