【数据结构与算法】——单链表的原理及C语言实现

数据结构与算法——链表原理及C语言实现

  • 链表的原理
  • 链表的基本属性设计
    • 创建一个空链表
    • 链表的遍历(显示数据)
    • 释放链表内存空间
  • 链表的基本操作设计(增删改查)
    • 链表插入节点
    • 链表删除节点
    • 链表查找节点
    • 增删改查测试程序
  • 链表的复杂操作程序设计
    • 单链表的反转
    • 相邻节点最大值
    • 有序链表的合并
    • 链表的排序

参考博文1:【数据结构与算法】程序内功篇三–单链表
参考博文2:链表基础知识详解(非常详细简单易懂)
参考博文3:关于链表,看这一篇就足够了!(新手入门)
参考博文4:单链表——单链表的定义及基本操作

链表的原理

链表含义
  由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表

单链表的特点:

  • 单链表不要求逻辑上相邻的两个元素在物理位置上也相邻,因此链表两个节点的存储空间不相邻。
  • 单链表是非随机的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。
  • 对于每个链表结点,分为存放数据的数据域以及存放下个节点地址的地址域

链表节点的定义:

typedef int data_t;//结点定义
typedef struct node{data_t data;		//结点数据域struct node *next;	//结点后继指针域
}listNode;

链表的基本属性设计

创建一个空链表

  通常会用头指针来标识一个单链表,头指针为NULL时表示一个空表。但是,为了操作方便,会在单链表的第一个结点之前附加一个结点,称为头结点。头结点的数据域可以不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的第一个元素结点。

创建空链表(头指针)主要分为:①申请节点内存空间  ②成员变量赋初始值  ③返回头节点 三大步骤:

  • 功能:创建一个空链表  node为虚拟头节点
  • 参数:void
  • 返回值:头节点地址
/*
功能:创建一个空链表  node为虚拟头节点
参数:void
返回值:头节点地址
*/
listNode* link_create()
{//申请内存空间listNode* node = (listNode *)malloc(sizeof(listNode));if(node == NULL){printf("link_create: malloc error\n");return NULL;}//链表成员变量赋值node->data = 0;node->next = NULL;//返回链表地址return node;
}

链表的遍历(显示数据)

第一步:输出第一个节点的数据域,输出完毕后,让指针保存后一个节点的地址

第二步:输出移动地址对应的节点的数据域,输出完毕后,指针继续后移

第三步:以此类推,直到节点的指针域为NULL

通过遍历链表读取链表的数据并显示:

  • 功能:显示链表数据
  • 参数:para: 链表头
  • 返回值:成功返回0   失败返回-1
/*
功能:显示链表数据
参数:para: 链表头   
返回值:成功返回0;    失败返回-1
*/
int link_show(listNode* head)
{//入口参数检查if(head == NULL)return -1;//遍历链表 while(head->next != NULL){printf("%d ", head->next->data);head = head->next;}printf("\n");return 0;
}

释放链表内存空间

通过遍历链表节点,释放每个节点的内存空间

  • 功能:释放链表内存空间
  • 参数:para: 链表头
  • 返回值: NULL
/*
功能:释放链表内存空间
参数:para :链表头          
返回值: NULL
*/
listNode* link_free(listNode* head)
{//入口参数检查if(head == NULL){printf("list_insert: para error\n");return NULL;}//封装临时节点listNode *temp = head;while(head != NULL){temp = head;//printf("free: %d\n", head->data);//这两行不能反 必须先指向下一个再释放当前地址head = head->next;	free(temp);}return NULL;
}

链表的基本操作设计(增删改查)

链表插入节点

同顺序表一样,向链表中增添元素,根据添加位置不同,可分为以下 3 种情况:

  • 插入到链表的头部(头节点之后),作为首元节点;
  • 插入到链表中间的某个位置;
  • 插入到链表的最末端,作为链表中最后一个数据元素;

虽然新元素的插入位置不固定,但是链表插入元素的思想是固定的,只需做以下两步操作,即可将新元素插入到指定的位置:

  • 将新结点的 next 指针指向插入位置后的结点;
  • 将插入位置前结点的 next 指针指向插入结点;

例如,我们在链表{1,2,3,4}的基础上分别实现在头部、中间部位、尾部插入新元素 5,其实现过程如下图 所示:

头插法程序设计:

  • 功能:链表头插法插入数据
  • 参数:para1:链表头    para2:插入的数据
  • 返回值:成功返回0;   失败返回-1
    /*
    功能:链表头插法插入数据
    参数:para1: 链表头  	para2: 插入的数据
    返回值:成功返回0;    失败返回-1
    */
    int link_push_front(listNode* head, data_t value)
    {//入口参数检查if(head == NULL)return -1;//封装节点listNode* node = (listNode *)malloc(sizeof(listNode));if(node == NULL){printf("link_push_front malloc error\n");return -1;}//头插法node->data = value;			//插入行节点数据node->next = head->next;	//将新节点连接到原来的头head->next = node;			//更新链表头return 0;
    }
    

任意位置插入元素程序设计:

  • 功能:在链表特定位置插入一个元素
  • 参数: para1:链表头    para2:插入的元素值    para3:特定位置的索引
  • 返回值: 失败返回-1    成功返回0
    /*
    功能:在链表特定位置插入一个元素
    参数:	para1:链表头	para2:插入的元素值	para3:特定位置的索引
    返回值: 失败返回-1    成功返回0
    */
    int list_insert(listNode* head, data_t value, int index)
    {//入口参数检查if(head == NULL || index < 0){printf("list_insert: para error\n");return -1;}//封装节点listNode* node = (listNode *)malloc(sizeof(listNode));if(node == NULL){printf("link_push_front malloc error\n");return -1;}node->data = value;//遍历到目标索引处int pos = 0;while(pos < index && head->next != NULL){pos++; head = head->next;}//索引过大if(head->next == NULL && index - pos > 0){printf("index invalid\n");return -1;}//插入数据node->next = head->next;head->next = node;return 0;
    }
    

尾插法程序设计:

  • 功能:链表尾插法插入数据
  • 参数:para1: 链表头    para2:插入的数据
  • 返回值:成功返回0;     失败返回-1
    /*
    功能:链表尾插法插入数据
    参数:para1: 链表头    para2: 插入的数据
    返回值:成功返回0;     失败返回-1
    */
    int link_push_back(listNode* head, data_t value)
    {//入口参数检查if(head == NULL)return -1;//封装节点listNode *node = (listNode *)malloc(sizeof(listNode));if(node == NULL){printf("link_push_back malloc error\n");return -1;}//新节点赋值node->data = value;node->next = NULL;//遍历链表 while(head->next != NULL){head = head->next;}//尾插入节点head->next = node;return 0;
    }
    

链表删除节点

  从链表中删除指定数据元素时,实则就是将存有该数据元素的节点从链表中摘除,但作为一名合格的程序员,要对存储空间负责,对不再利用的存储空间要及时释放。因此,从链表中删除数据元素需要进行以下 2 步操作:

  • 将结点从链表中摘下来;
  • 手动释放掉结点,回收被结点占用的存储空间;

其中,从链表上摘除某节点的实现非常简单,只需找到该节点的直接前驱节点 temp,执行一行程序:

temp->next = temp->next->next;

根据数据值删除某个节点

  • 功能:根据数据值 删除某个节点
  • 参数: para1:链表头  para2:删除数值
  • 返回值: 失败返回-1  成功返回0
    /*
    功能:根据数据值 删除某个节点
    参数:	para1:链表头	para2:删除数值
    返回值: 失败返回-1    成功返回0
    */
    int list_delete_val(listNode* head, int val)
    {//入口参数检查if(head == NULL){printf("list_insert: para error\n");return -1;}//遍历链表while(head->next != NULL && head->next->data != val){head = head->next;}//链表中无该数据if(head->next == NULL && head->data != val){printf("no such value\n");return -1;	}listNode *temp = head->next;	//暂存需释放空间的节点head->next = head->next->next;	//跳跃拉链,即删除了中间节点free(temp);						//释放节点temp = NULL;					//避免野指针return 0;	
    }
    

根据索引删除某个节点

  • 功能:根据索引 删除某个节点 (链表其实没有所谓的索引,即第几个节点-1)
  • 参数: para1:链表头   para2:删除的索引
  • 返回值: 失败返回-1    返回 0
    /*
    功能:根据索引 删除某个节点 (链表其实没有所谓的索引,即第几个节点-1)
    参数:	para1:链表头	para2:删除的索引
    返回值: 失败返回-1    成功返回0
    */
    int link_delete_index(listNode* head, int index)
    {//入口参数检查if(head == NULL || index < 0){printf("link_delete_index: para error\n");return -1;}//遍历链表int pos = 0;while(pos < index && head != NULL){//节点遍历完了if(head->next == NULL){	printf("index error\n");return -1;}pos++;					//索引head = head->next;		//指针偏移}//printf("data: %d\n", head->data);//判断后一个元素是否为空if(head->next == NULL){printf("index error\n");return -1;}listNode *temp = head->next;	//暂存需释放空间的节点head->next = head->next->next;	//跳跃拉链,即删除了中间节点free(temp);						//释放节点temp = NULL;					//避免野指针return 0;	
    }
    

链表查找节点

按数值查找:
  查找数据value在单链表link中的节点索引。
  算法思想:从单链表的第一个结点开始,依次比较表中各个结点的数据域的值,若某结点数据域的值等于value,则返回该节点的索引;若整个单链表中没有这样的结点,则返回-1。

  • 功能:查找某个元素的下标索引
  • 参数:para1:链表头 para2:查找的某个元素值
  • 返回值: 失败返回-1  成功返回元素的下标索引
/*
功能:查找某个元素的下标索引
参数:para1:链表头	para2:查找的某个元素值
返回值: 失败返回-1    成功返回元素的下标索引
*/
int list_search(listNode* head, data_t val)
{//入口参数检查if(head == NULL){printf("list_insert: para error\n");return -1;}//pos 记录下标位置int pos = -1;while(head->next != NULL){pos++;if(head->next->data == val)	//判断是否存在valreturn pos;head = head->next;}return -1;
}

增删改查测试程序

//-------------测试程序-------------
void link_test()
{listNode *head = link_create();int data1[] = {-3, 2, 9, 5, 101};int data2[] = {4, 100, 0};//尾插法插入数据for( int i = 0; i < 5; i++)link_push_back(head, data1[i]);//头插法插入数据for( int i = 0; i < 3; i++)	link_push_front(head, data2[i]);//特定位置插入数据link_insert(head,66,1);//显示原链表printf("src link:");link_show(head);link_delete_index(head, 2);	//删除下标为2的节点link_delete_val(head, 66);	//删除数据为66的节点printf("delete:  ");link_show(head);//查找int ret = link_getVal( head, 2);int idx = link_search( head, 101);printf("data[2]: %d\n", ret);printf("101's index: %d\n", idx);head = link_free(head);	
}

链表的复杂操作程序设计

单链表的反转

算法思路: 依次取原链表中各结点,将其作为新链表首结点插入head结点
即获取原链表的每个节点,在新链表进行头插法插入:

  1. 判断是否为空 / 是否只有1个节点
  2. 断开链表,一分为二,分为第一个节点和后面链表
  3. 遍历从第二个后面起的节点,头插法循环插入

  • 功能:单链表的反转
  • 参数: para:   链表头
  • 返回值: 失败返回-1   成功返回0
int link_reverse(listNode* head)
{//入口参数检查if(head == NULL ){printf("head is NULL.\n");return -1;}//只有一个节点if(head->next == NULL || head -> next ->next == NULL ){return 0;}//p指向待操作的节点listNode *p = head->next->next;	//新链表头head->next->next = NULL;		//链表一分为二listNode *q = p;//遍历后续节点,以尾插法插入新的链表while(p != NULL){q = p;p = p->next;//头插法 插入qq->next = head->next;head->next = q;}return 0;
}

测试程序:

void link_reverse_test()
{listNode *head = link_create();int data1[] = {-3, 2, 9, 5, 3};for(int i = 0; i < 5; i++)link_push_back(head, data1[i]);//打印原链表printf("link: ");link_show(head);//翻转链表link_reverse(head);//打印翻转后的链表printf("reverse: ");link_show(head);//释放内存空间head = link_free(head);
}

相邻节点最大值

算法思路: 设q,p分别为链表中相邻两结点指针,其中p在前,q在后,求q->data + q->data为最大的那一组值,返回其相应的指针q即可:

  1. 节点个数 <= 2,退出
  2. 初始化辅助变量(遍历节点指针p,q(p在前,q在后),两数之和sum,新节点指针ret指向head,并以头节点一分为二)
  3. 遍历p和q,以及sum

  • 功能:求相邻节点最大值,返回最大值第一个节点地址,最大值通过参数传递
  • 参数: para1:链表头 para2:最大和的值的地址
  • 返回值: 失败返回NULL 成功返回第一个节点指针
//求链表中相邻两节点data值之和为最大的第一节点的指针
/*
功能:求相邻节点最大值,返回最大值第一个节点地址
最大值通过参数传递
参数:	para1:链表头 	para2:最大和的值的地址
返回值: 失败返回NULL  成功返回第一个节点指针
*/
listNode *list_adjmax(listNode *head, data_t *value)
{if(head == NULL){printf("head is NULL\n");return NULL;}if(head->next == NULL || head->next->next == NULL || head->next->next->next == NULL)return head;//构造辅助变量listNode *ret = head->next;			//结果链表尾指针listNode *p   = head->next->next;	//遍历链表的指针, p在前面listNode *q   = head->next;			//遍历链表的指针, q在后data_t max = q->data + p->data ;	//初始化两数之和while(p->next != NULL){//p q更新p = p->next;q = q->next;//比较最大值if(q->data + p->data > max){max = q->data + p->data;	//更新最大值ret = q;					//更新最大值第一个节点}}//返回相邻最大值的第一个节点指针,并通过参数传回最大值*value = max;return ret;
}

测试程序:

void list_adjmax_test()
{listNode *head = link_create();int data1[] = {-3, 2, 9, 5, 3};for(int i = 0; i < 5; i++)link_push_back(head, data1[i]);//打印原链表printf("link: ");link_show(head);//计算最大两数之和及第一个节点int sum;listNode *ret = list_adjmax(head, &sum);//打印新节点数及其两数最大之和printf("data: %d\nsum: %d", ret->data, sum);//释放内存空间head = link_free(head);	
}

有序链表的合并

算法思想: 设指针p、q分别指向表A和B中的结点,若p -> data <= q -> data,则p进入结果表,否则q结点进入结果表。

  1. 参数判断(链表是否为空)
  2. 分别将链表一分为二,p,q分别指向两个链表的新的头,结果存放在以ret为尾节点的链表中
  3. 通过p,q指针遍历两个链表,将小的数值插入到ret结果链表中形成新的合并链表
  • 功能:合并两个链表,合并至head1
  • 参数: para1: 链表1头节点  para2: 链表2头节点
  • 返回值: 失败返回 -1  成功返回 0
//合并两个有序链表
/*
功能:合并两个链表,合并至head1
参数:	para1:链表1头节点	para2:链表2头节点
返回值: 失败返回-1  成功返回0
*/
int link_merge(listNode *head1, listNode *head2)
{//入口参数检查if( head1 == NULL || head2 == NULL){printf("head1 || head2 error\n");return -1;}//变量初始化listNode *p = head1->next;listNode *q = head2->next;listNode *ret = head1;head1->next = NULL;head2->next = NULL;while(p != NULL && q != NULL){if(p->data <= q->data){ret->next = p;		//p接入ret链表p = p->next;		//更新pret = ret->next;	//更新新表尾ret->next = NULL;	//置空新表尾}else{ret->next = q;		//q接入ret链表q = q->next;		//更新qret = ret->next;	//更新新表尾ret->next = NULL;	//置空新表尾}}//把多的p或q接入到ret链表if( p != NULL)ret->next = p;if( q != NULL)ret->next = q;return 0;
}

测试程序:

void link_merge_test()
{listNode *head1 = link_create();listNode *head2 = link_create();int data1[] = {1, 2, 4, 6, 8};int data2[] = {2, 5, 6, 22, 96, 128};//插入数据for(int i = 0; i < 5; i++)link_push_back(head1, data1[i]);for(int i = 0; i < 6; i++)link_push_back(head2, data2[i]);	//打印原有序链表printf("link1: ");link_show(head1);printf("link2: ");link_show(head2);//合并printf("merge: ");link_merge(head1, head2);link_show(head1);//去重printf("purge: ");link_purge(head1);link_show(head1);head1 = link_free(head1);	head2 = link_free(head2);	
}

链表的排序

  • 如果链表为空或只有一个结点,不需要排序
  • 先将第一个结点与后面所有的结点依次对比数据域,只要有比第一个结点数据域小的,则交换位置 ,交换之后,拿新的第一个结点的数据域与下一个结点再次对比,如果比他小,再次交换,以此类推
  • 第一个结点确定完毕之后,接下来再将第二个结点与后面所有的结点对比,直到最后一个结点也对比完毕为止
int link_sort(listNode *head )
{//头节点为空if (head == NULL){printf("head is NULL\n");return -1;}//只有1个节点if (head->next == NULL){printf("only one node\n");return 0;}listNode *q, *p, temp;p = head->next;			//从第一个节点开始while (p->next != NULL){q = p->next;		//q从基准元素的下个元素开始while (q != NULL){if (p->data > q->data)	//后面的元素小{//交换值temp = *q;			*q = *p;*p = temp;//交换地址temp.next = q->next;q->next = p->next;p->next = temp.next;}q = q->next;}p = p->next;}return 0;
}

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

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

相关文章

Vulnhub billu b0x

0x01 环境搭建 1. 从官方下载靶机环境&#xff0c;解压到本地&#xff0c;双击OVF文件直接导入到vmware虚拟机里面。2. 将虚拟机的网络适配器调成NAT模式&#xff0c;然后开机即可进行操作了。 0x02 主机发现 nmap -sn 192.168.2.0/24 成功获取靶机IP为192.168.2.129。 0x0…

本次安装Visual Studio 所用的安装程序不完整。请重新运行VisualStudio安装程序以解决此问题

今天点开VS的时候遇到了这个问题 因为昨天升级到一半电脑关机了&#xff0c;今天打开软件遇到如下错误&#xff0c; 解决办法很简单&#xff0c;找到安装目录进入Installer文件夹 我的目录在C:\Program Files (x86)\Microsoft Visual Studio\Installer 找到vs_installer.exe…

【python】python爱心代码

一、实现效果&#xff1a; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 二、准备工作 &#xff08;1)、导入必要的模块&#xff1a; 代码首先导入了需要使用的模块&#xff1a;requests、lxml和csv。 import requests from lxml import etree import csv 如果出现…

查找单词-算法(深度优先)

题目 给定一个二维数组与一个单词&#xff0c;数组中每个元素为大写字母&#xff0c;判断单词是否出现在数组中。 如二维数组&#xff1a; char[][] map {{A, B, C, E}, {S, F, C, S}, {A, D, E, E}}; 目标单词&#xff1a; ABCCEE 解题 深度优先&#xff0c;并且走过的…

03哈希表:242、有效的字母异位词

242、有效的字母异位词 文章目录 242、有效的字母异位词方法一&#xff1a;暴力破解法方法二、 哈希法 重点&#xff1a;哈希可以用数组代替表示&#xff0c;下标用与a的位置绝对值 暴力破解法&#xff1a;两层for循环&#xff0c;同时记录字母次数哈希法&#xff1a;第一个字符…

C#写个小工具,把多个word文档进行合并成一个word文档

先要安装包 帮助类WordDocumentMerger&#xff0c;用于处理word合并功能 using System; using System.Collections.Generic; using System.Text; using Microsoft.Office.Interop.Word; using System.Reflection; using System.IO; using System.Diagnostics;namespace WordH…

分别用JavaScript,Java,PHP,C++实现桶排序的算法(附带源码)

桶排序是计数排序的升级版。它利用了函数的映射关系&#xff0c;高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效&#xff0c;我们需要做到这两点&#xff1a; 在额外空间充足的情况下&#xff0c;尽量增大桶的数量使用的映射函数能够将输入的 N 个数据均匀的分…

关闭windows系统的自动更新的6种方法 详细介绍

关闭Windows系统的自动更新可以通过多种方法实现&#xff0c;以下将详细介绍六种不同的方法。请注意&#xff0c;关闭自动更新可能会使您的系统面临安全风险&#xff0c;因为您将不会及时接收到最新的安全补丁和系统更新。在执行以下任何操作之前&#xff0c;请确保您了解潜在的…

多线程读写文件问题

多线程读写同个文件会不会有访问冲突或者异常&#xff1f;我们写个程序来测试一下 /*** Created by fangruibin* 测试多线程读写文件*/#include <iostream> #include <pthread.h> #include <unistd.h> #include <string.h>const char* fileName &quo…

【C语言】字符串函数介绍

目录 前言&#xff1a; 1. strlen 函数 函数介绍 strlen 函数的使用 strlen 函数的模拟实现 2. strcpy 函数 函数介绍 strcpy 函数的使用 strcpy 函数的模拟实现 3. strcat 函数 函数介绍 strcat 函数的使用 strcat 函数的模拟实现 4. strcmp 函数 函数介绍 st…

前端工程化之:webpack1-12(常用扩展)

目录 前言 一、CleanWebpackPlugin 二、HtmlWebpackPlugin 三、CopyPlugin 四、webpack-dev-server 五 、file-loader 六、url-loader 七、路径问题 前言 由于 webpack 、 webpack-cli 、 webpack-dev-server 会存在版本不兼容问题&#xff0c;所以这里使用的版本如下&…

4K Video Downloader forMac/win:畅享高清视频下载的终极利器!

在如今的数字时代&#xff0c;高清视频已经成为人们生活中不可或缺的一部分。无论是观看精彩的电影、音乐视频&#xff0c;还是学习教育类的在线课程&#xff0c;我们都希望能够以最清晰流畅的方式来欣赏。而为了满足这一需求&#xff0c;我们需要一款功能强大的高清视频下载软…

工业平板电脑定制_三防平板电脑安卓主板厂家

工业平板电脑具有IP68级三防品质&#xff0c;采用高强度工业材质制造&#xff0c;结构稳固坚韧&#xff0c;具备较高的抗冲击和防震能力。隔空减震技术进一步加强了产品的抗冲击和防震动功能。广泛应用于工控、医疗、电信、电力、工业自动化设备、汽车检测、制造业等多个领域&a…

Flink实时数仓同步:快照表实战详解

一、背景 在大数据领域&#xff0c;初始阶段业务数据通常被存储于关系型数据库&#xff0c;如MySQL。然而&#xff0c;为满足日常分析和报表等需求&#xff0c;大数据平台采用多种同步方式&#xff0c;以适应这些业务数据的不同存储需求。这些同步存储方式包括离线仓库和实时仓…

MySQL语句 |条件语句 IFNULL 和 COALESCE 的区别

在MySQL中&#xff0c;IFNULL和COALESCE都是用来处理NULL值的函数&#xff0c;但它们之间存在一些重要的差异。 函数定义 IFNULL(expr1, expr2): 如果expr1为NULL&#xff0c;则返回expr2&#xff0c;否则返回expr1。COALESCE(value1, value2, ..., valueN): 返回参数列表中的…

机器人中的数值优化进阶|【三】三次样条曲线推导(下)

机器人中的数值优化进阶|【三】三次样条曲线推导&#xff08;下&#xff09; 接之前的内容&#xff0c;现在开始考虑势场函数 P ( η 1 , . . . , η n − 1 ) 1000 ∑ i 1 n − 1 ∑ j 0 m max ⁡ ( r j − ∣ ∣ η i − o j ∣ ∣ , 0 ) P(\eta_1,...,\eta_{n-1}) 100…

C语言入门到精通之练习35:打印出杨辉三角形(要求打印出10行)

题目&#xff1a;打印出杨辉三角形&#xff08;要求打印出10行&#xff09;。 程序分析&#xff1a; 结构如下图所示&#xff1a; 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1代码如下&#xff1a; // Created by www.erdangjiade.com 15/11/9. //#incl…

学习方法分享

工作上的代码实现&#xff0c;不要过度设计&#xff0c;不要想着炫技&#xff0c;要简单务实&#xff0c;“大道至简”。 学习一个方向&#xff08;模块化&#xff09;的知识&#xff0c;不经意间就会涉及到另一个领域&#xff0c;比如从消息队列存储的顺序读/写&#xff0c;延…

计算机网络作业答案(ip地址划分,滑动窗口,距离向量算法)

做一个计算机网络作业答案的存档 6.某单位申请到了一个B类IP地址&#xff0c;其网络标识为130.53&#xff0c;现进行子网划分&#xff0c;若选用的子网掩码为 255.255.224.0&#xff0c;请问:(1&#xff09;可划分为多少个子网?(2)每个子网中的主机数最多为多少台?(3&#…

MySQL数据库入门

MySQL数据库概述 1&#xff0c;为什么要使用数据库2&#xff0c;数据库的相关概念3&#xff0c;常见的数据库管理系统4&#xff0c;MySQL介绍5&#xff0c;关系型数据库和非关系型数据库6&#xff0c;关系型数据库的设计规则7&#xff0c;表的关联关系7.1&#xff0c;一对一7.2…