Java 数据结构篇-实现双链表的核心API
🔥博客主页: 小扳_-CSDN博客
❤感谢大家点赞👍收藏⭐评论✍
文章目录
1.0 双链表的说明
1.1 双链表 - 创建
1.2 双链表 - 根据索引查找节点
1.3 双链表 - 根据索引插入节点
1.4 双链表 - 头插节点
1.5 双链表 - 尾插
1.6 双链表 - 根据索引来删除节点
1.7 头删节点
1.8 尾删节点
1.9 实现迭代器循环
2.0 双链表完整的实现代码
3.0 环形双链表的说明
3.1 环形双链表 - 创建
3.2 环形双链表 - 头插节点
3.3 环形双链表 - 尾插节点
3.4 环形双链表 - 头删节点
3.5 环形双链表 - 尾删节点
3.6 环形链表 - 根据值来删除节点
4.0 环形双链表完整的实现代码
1.0 双链表的说明
双链表是一种数据结构,其中每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点。双链表可以在任意位置插入或删除节点,而不需要像单链表那样遍历整个链表来找到需要操作的位置。双链表可以用于实现栈、队列、以及其他需要快速插入和删除操作的数据结构。由于每个节点包含两个指针,双链表的内存占用量通常比单链表更大。
1.1 双链表 - 创建
把双链表封装成一个类,类中还需要封装一个节点类 Node,该节点类的成员有指向前一个节点的变量 Node prev,值 value ,指向后一个节点的变量 Node next 。
代码如下:
public class MyDoubleLists{private final Node hand;private final Node tail;private static class Node {public Node prev;public Node next;public int value;public Node(Node prev, int value, Node next) {this.prev = prev;this.next = next;this.value = value;}}public MyDoubleLists() {hand = new Node(null,0,null);tail = new Node(hand,-1,null);hand.next = tail;tail.prev = hand;}}
注意外部类中,还需要定义头节点,尾节点,再利用外部类的构造器中就可以完成对头尾节点的初始化了。内部类中的节点类建议用静态来修饰。
1.2 双链表 - 根据索引查找节点
由于这个方法可以为其他几个方法提供服务,因此,把这个方法独立出来。实现思路为:开始的节点应为 hand,循环终止条件为:p == tail 当指向尾节点的那一刻就该结束循环了。还要加一个变量 i = -1 ,每一次循环结束要进行 i++ ,当 i == index 时,找到了该索引的节点,返回该节点即可,若循环结束还是没找到,就得返回 null 。
代码如下:
//根据索引查找节点private Node findNode(int index) {int i = -1;for (Node p = hand; p !=tail ; p = p.next,i++){if (i == index) {return p;}}return null;}
这个方法一般不会对外开发,因此,加上 private 来修饰,当 i == -1 时,返回的时头节点,所以一开始的节点为 hand 。对外是索引从 0 开始才会存储值的,对于头节点存储什么值是不关心的。
1.3 双链表 - 根据索引插入节点
根据索引插入节点,提前需要准备好该节点的前一个节点 prev、该节点的后一个节点 next 。通过以上已经实现的方法来找到插入位置的前一个结点,prev = findNode(index - 1),后一个节点也就可以找到了,next = prev.next。
代码如下:
//根据索引插入节点public void insert(int index, int value) {Node p = findNode(index - 1);if (p == null){throw new RuntimeException("用索引访问失败");}Node prev = p;Node next = prev.next;Node insertNode = new Node(prev, value,next);prev.next = insertNode;next.prev = insertNode;}
prev.next 指向新的节点,next.prev 指向上一个节点。新的节点的头节点的引用为 prev,尾节点为 next 。
1.4 双链表 - 头插节点
其实这个方法就比较简单了,这个就是根据索引 0 来插入节点的,就是一个索引等于0的特例,所以可以直接调用已经实现的 insert(0,int value) 方法。
代码如下:
//头插节点public void addFirst(int value) {insert(0,value);}
1.5 双链表 - 尾插
对尾部的操作是双链表的一个很大的优势,对尾部的查询、增加节点、删除节点效率都很快,因为对尾节点是有记录的,就不用从头开始来查找尾部节点了,直接可以得到。
实现方法的思路为:需要找到插入的前一个节点,插入的后一个节点肯定是尾节点,所以,可以通过 prev = tail.prev,来找到插入的前一个节点。
代码如下:
//尾插节点public void addLast(int value) {Node lats = tail;Node prev = lats.prev;Node addNode = new Node(prev,value,lats);prev.next = addNode;lats.prev = addNode;}
新的节点的前一个节点为 prev ,后节点为 tail,prev.next 与 tail.prev 就要更改为指向新的节点了。
1.6 双链表 - 根据索引来删除节点
先通过已经实现的 findNode() 方法来找到该索引的节点,还有找到删除该节点的前一个节点与后一个节点。
代码如下:
//根据索引来删除节点public void remove(int index) {Node prev = findNode(index - 1);if (prev == null) {throw new RuntimeException("用索引来删除数据失败!");}Node remove = prev.next;if (remove == tail) {throw new RuntimeException("用索引来删除数据失败!");}Node next = remove.next;prev.next = next;next.prev = next;}
接着就可以将要删除的前一个节点指向要删除的节点后一个节点,但是考虑两种情况,第一种,当要删除的节点没找到,就要抛出异常了。第二种,当发现要删除的节点为 tail 时需要抛出异常,总不能自己把自己的尾巴 "切了吧" 然而不用考虑是否把头节点删除,因为要删除的节点总是拿不到头节点。
1.7 头删节点
当索引为0时,就是头删,是 remove(0) 方法的一个特例。可以直接来调用根据索引来删除节点的方法。
代码如下:
//头删节点public void removeFirst() {remove(0);}
1.8 尾删节点
双链表尾删的效率是很高的,因为对尾节点是有记录的。
代码如下:
//尾删节点public void removeLast() {Node remove = tail.prev;if (remove == hand){throw new RuntimeException();}Node prev = remove.prev;prev.next = tail;tail.prev = prev;}
需要找到三个节点,要删除的节点、删除节点的前一个节点、还有尾节点。需要注意的是,判断要删除的节点为头节点,需要抛出异常,总不能自己把自己的 " 头部 " 给切了吧。
1.9 实现迭代器循环
这个完成 Iterable 接口,创建新的该接口子类对象,重写两个方法即可。
代码如下:
//实现迭代器循环@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = hand.next;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};}
需要注意的是,头节点的值是不用在乎的,所以遍历开始为 hand.next ,循环结束条件为,p == tail,遍历到尾节点就要终止了。
2.0 双链表完整的实现代码
import java.util.Iterator;public class MyDoubleLists implements Iterable<Integer>{private final Node hand;private final Node tail;private static class Node {public Node prev;public Node next;public int value;public Node(Node prev, int value, Node next) {this.prev = prev;this.next = next;this.value = value;}}public MyDoubleLists() {hand = new Node(null,0,null);tail = new Node(hand,-1,null);hand.next = tail;tail.prev = hand;}//根据索引查找节点private Node findNode(int index) {int i = -1;for (Node p = hand; p !=tail ; p = p.next,i++){if (i == index) {return p;}}return null;}//根据索引插入节点public void insert(int index, int value) {Node p = findNode(index - 1);if (p == null){throw new RuntimeException("用索引访问失败");}Node prev = p;Node next = prev.next;Node insertNode = new Node(prev, value,next);prev.next = insertNode;next.prev = insertNode;}//头插节点public void addFirst(int value) {insert(0,value);}//尾插节点public void addLast(int value) {Node lats = tail;Node prev = lats.prev;Node addNode = new Node(prev,value,lats);prev.next = addNode;lats.prev = addNode;}//根据索引来删除节点public void remove(int index) {Node prev = findNode(index - 1);if (prev == null) {throw new RuntimeException("用索引来删除数据失败!");}Node remove = prev.next;if (remove == tail) {throw new RuntimeException("用索引来删除数据失败!");}Node next = remove.next;prev.next = next;next.prev = next;}//头删节点public void removeFirst() {remove(0);}//尾删节点public void removeLast() {Node remove = tail.prev;if (remove == hand){throw new RuntimeException();}Node prev = remove.prev;prev.next = tail;tail.prev = prev;}//根据索引来查询数据public int get(int index) {Node find = findNode(index);if (find == null){throw new RuntimeException("根据该索引找不到数据");}return find.value;}//实现迭代器循环@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = hand.next;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};}}
3.0 环形双链表的说明
环形双链表是一种数据结构,它类似于双向链表,但是链表的最后一个节点指向第一个节点,形成一个环形结构。简单来说,先对比与一般的双链表,环形双链表就是头尾节点都是同一个节点。
3.1 环形双链表 - 创建
把环形双链表看成一个对象,该类中需要封装一个节点的内部类,对外不开放的,需要用限制修饰符来修饰。外部类中的成员变为 sentinel ,即作为头节点,也作为尾节点。
代码如下:
public class MyAnnularDoubleList{private final Node sentinel;private static class Node {public Node prev;public int value;public Node next;public Node(Node prev, int value, Node next) {this.prev = prev;this.value = value;this.next = next;}}public MyAnnularDoubleList() {sentinel = new Node(null,0,null);sentinel.prev = sentinel;sentinel.next = sentinel;}}
在创建环形双链表时,在用无参构造器就可以先把 sentinel 初始化了。
3.2 环形双链表 - 头插节点
根据 next = sentinel.next 就可以得到插入点的下一个节点,就可以把新节点的指向的前一个节点来指向 sntinel,新节点的指向后一个节点来指向 next 。
这里需要考虑一种情况,假设,该环形双链表中就只有一个 sentinel 节点,以上阐述的思路还能不能用呢?答案时可以的,如果实在理解不了的话,可以把一个 sentinel 节点,想象成两个 sentinel 节点,效果都是一样的,都是指向自己嘛。
代码如下:
//头插节点public void addFirst(int value) {Node hand = sentinel;Node tail = sentinel.next;Node addNode = new Node(hand,value,tail);hand.next = addNode;tail.prev = addNode;}
3.3 环形双链表 - 尾插节点
根据 prev = sentinel.prev 来找到插入节点的前一个的节点,插入节点的后一个节点就是 sentinel ,新节点的指向前的节点为 prev,新节点的指向后的节点为 sentinel ,接着 prev.next 指向新节点,sentinel.prev 指向新节点。
代码如下:
//尾插节点public void addLast(int value) {Node prev = sentinel.prev;Node next = sentinel;Node addNode = new Node(prev,value,next);prev.next = addNode;next.prev = addNode;}
同理,不需要额外考虑当节点只有一个时,以上代码依旧可以实现尾插节点。
3.4 环形双链表 - 头删节点
根据 remove = sentinel.next ,可以得到需要删除的节点,再由 next = remove.next,得到删除节点的后一个节点,这样三个节点后已知了,santinel.next 指向 next ,next.prev 指向sentinel ,剩下的没有被引用的节点(对象),会被 JVM 自动回收。
代码如下:
//头删节点public void removeFirst() {Node remove = sentinel.next;if (remove == sentinel) {throw new RuntimeException("删除失败!");}Node next = remove.next;sentinel.next = next;next.prev = sentinel;}
需要注意的是,当删除的节点为 sentinel 需要抛出异常,但是个人感觉不加判断也可以,sentinel 根本不会被删除,即使只有 sentinel 一直被删除。
3.5 环形双链表 - 尾删节点
根据 remove = sentinel.prev 得到需要删除的节点,通过 prev = remove.prev 得到需要删除的前一个节点,prev.next 指向 sentinel,sentinel.prev 指向 prev 即可。
代码如下:
//尾删节点public void removeLast() {Node remove = sentinel.prev;Node prev = remove.prev;prev.next = sentinel;sentinel.prev = prev;}
同样的,当删除的节点为 sentinel 需要抛出异常,但是个人感觉不加判断也可以,sentinel 根本不会被删除,即使只有 sentinel 一直被删除。
3.6 环形链表 - 根据值来删除节点
先独立一个方法,根据值来查询节点,一开始的循环节点为 sentinel.next ,对于 sentinel 里面的值是什么根本不在乎的。循环终止条件为:p == sentinel 已经转完一圈了。找到就返回该节点,找不到就返回 null 。删除的原理是一样的,得先找到三个节点,然后把前后节点直接关联起来。
代码如下:
//根据值来删除节点private Node findValue (int value) {for (Node p = sentinel.next; p != sentinel; p = p.next) {if (p.value == value) {return p;}}return null;}public void removeValue (int value) {Node remove = findValue(value);if (remove == null) {throw new RuntimeException("找不到该数据来删除相对应的节点");}Node prev = remove.prev;Node next = remove.next;prev.next = next;next.prev = prev;}
需要注意的是,当接收到的节点为 null 时,需要抛出异常,找不到对应该值的节点。
4.0 环形双链表完整的实现代码
import java.util.Iterator;public class MyAnnularDoubleList implements Iterable<Integer>{private final Node sentinel;private static class Node {public Node prev;public int value;public Node next;public Node(Node prev, int value, Node next) {this.prev = prev;this.value = value;this.next = next;}}public MyAnnularDoubleList() {sentinel = new Node(null,0,null);sentinel.prev = sentinel;sentinel.next = sentinel;}//头插节点public void addFirst(int value) {Node hand = sentinel;Node tail = sentinel.next;Node addNode = new Node(hand,value,tail);hand.next = addNode;tail.prev = addNode;}//尾插节点public void addLast(int value) {Node prev = sentinel.prev;Node next = sentinel;Node addNode = new Node(prev,value,next);prev.next = addNode;next.prev = addNode;}//头删节点public void removeFirst() {Node remove = sentinel.next;if (remove == sentinel) {throw new RuntimeException("删除失败!");}Node next = remove.next;sentinel.next = next;next.prev = sentinel;}//尾删节点public void removeLast() {Node remove = sentinel.prev;Node prev = remove.prev;prev.next = sentinel;sentinel.prev = prev;}//根据值来删除节点private Node findValue (int value) {for (Node p = sentinel.next; p != sentinel; p = p.next) {if (p.value == value) {return p;}}return null;}public void removeValue (int value) {Node remove = findValue(value);if (remove == null) {throw new RuntimeException("找不到该数据来删除相对应的节点");}Node prev = remove.prev;Node next = remove.next;prev.next = next;next.prev = prev;}//实现迭代器@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = sentinel.next;@Overridepublic boolean hasNext() {return p != sentinel;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};} }
相关文章:

Java 数据结构篇-实现双链表的核心API
🔥博客主页: 小扳_-CSDN博客 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 双链表的说明 1.1 双链表 - 创建 1.2 双链表 - 根据索引查找节点 1.3 双链表 - 根据索引插入节点 1.4 双链表 - 头插节点 1.5 双链表 - 尾插 1.6 双链表 - 根据索引来…...

电脑如何截屏?一起来揭晓答案!
在数字时代,截屏已经成为我们日常生活和工作中的必备技能。无论是为了捕捉有趣的网络瞬间,保存重要信息,还是为了协作和教育,电脑截屏都是一个强大而方便的工具。本文将介绍三种电脑如何截屏的方法,以满足各种需求&…...
【实战-08】flink 消费kafka自定义序列化
目的 让从kafka消费出来的数据,直接就转换成我们的对象 mvn pom <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information …...
深入浅出 Django 异步编程
随着 Web 应用对性能的要求日益提高,异步编程成为了提升响应速度、提高系统吞吐量的重要手段。Django 作为一个成熟的 Python Web 框架,自 3.1 版本开始支持了异步编程。在本文中,我们将探讨 Django 异步编程的关键概念,并提供实际…...
力扣 138. 随机链表的复制
文章目录 1.解题思路2.代码实现 1.解题思路 在原先链表的每一个元素后面插入一个与前一个相同val的值的结点,然后由于是在原链表进行的操作,因此找每个random就变得很方便直接访问即可,此题目的精髓是cur1->randomp->random->next,看懂这串代码…...

STM32外部中断大问题
问题:一直进入中断,没有触发信号,也一直进入。 描述:开PA0为外部中断,刚刚很好,一个触发信号一个中断,中断函数没有丢,也没有抢跑,开PA1为外部中断也是,都很好…...

FPGA配置采集AR0135工业相机,提供2套工程源码和技术支持
目录 1、前言免责声明 2、AR0135工业相机简介3、我这里已有的 FPGA 图像处理解决方案4、设计思路框架AR0135配置和采集图像缓存视频输出 5、vivado工程1–>Kintex7开发板工程6、vivado工程1–>Zynq7100开发板工程7、上板调试验证8、福利:工程代码的获取 1、前…...

KubeSphere v3.4.0 部署K8S Docker + Prometheus + grafana
KubeSphere v3.4.0 部署K8S 1、整体思路2、修改linux主机名3、 离线安装3.1 问题列表3.2 执行命令成功列表 1、整体思路 将KubeSphere v3.4.0 安装包传输到其中一台机器修改Linux主机名(选取3台,修改为master01、master02、master03)安装官方…...
Codeforces Round 908 (Div. 2)题解
目录 A. Secret Sport 题目分析: B. Two Out of Three 题目分析: C. Anonymous Informant 题目分析: A. Secret Sport 题目分析: A,B一共打n场比赛,输入一个字符串由A和‘B’组成代表A赢或者B赢(无平局),因为题目说明这个人…...

Redis笔记 Redis主从同步
文章目录 Redis主从搭建主从架构主从数据同步原理全量同步增量同步repl_backlog原理 主从同步优化小结 Redis主从 搭建主从架构 单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。 主从数据…...

数据结构-Prim算法构造无向图的最小生成树
引子: 无向图如果是一个网,那么它的所有的生成树中必有一颗生成树的边的权值之和是最小的,我们称 这颗权值和最小的树为:“最小生成树”(MST)。 其中,一棵树的代价就是树中所有权值之和。 而…...

MFC串口通信(SerialPort)
目录 1、SerialPort类的介绍和使用: (1)、SerialPort类的功能介绍 (2)、SerialPort类提供接口函数的介绍 1)、InitPort函数 2)、控制串口监视线程函数 3)、获取事件,…...

Vim基本使用操作
前言:作者也是初学Linux,可能总结的还不是很到位 Linux修炼功法:初阶功法 ♈️今日夜电波:美人鱼—林俊杰 0:21━━━━━━️💟──────── 4:14 …...

【深蓝学院】手写VIO第8章--相机与IMU时间戳同步--作业
0. 题目 1. T1 逆深度参数化时的特征匀速模型的重投影误差 参考常鑫助教的答案:思路是将i时刻的观测投到world系,再用j时刻pose和外参投到j时刻camera坐标系下,归一化得到预测的二维坐标(这里忽略了camera的内参,逆深…...
Naocs配置中心配置映射List、Map、Map嵌套List等方式
一、配置映射List 1、常规逐个配置方式,示例如下: 代码: @Data @Configuration @ConfigurationProperties(prefix = "list-json-str") public class ConfListByJsonStr implements Serializable, InitializingBean {@ApiModelProperty("映射结果集")…...

如何通过CRM系统进行销售机会管理?
销售机会管理是在销售过程中对潜在客户的精细化管理,销售机会管理的本质是公司用于管理销售机会通用的工具和方法。对于希望建立长期客户关系的现代销售团队来说,CRM客户管理系统是必不可少的工具。那企业如何通过CRM系统进行销售机会管理? …...

解决idea启动tomcat控制台中文乱码
#1.tomcat日志中文乱码# 如图这种情况,一般在idea用tomcat跑一个web项目启动后tomcat日志在控制台打印出来会出现中文乱码的情况 解决方案1:tomcat的日志配置文件的编码修改,找到tomcat安装目录conf下的logging.properties,encod…...
vscode + cmake + opencv example
nice try on macos CMakeLists.txt cmake_minimum_required(VERSION 3.20) #添加OPENCV库 #指定OpenCV版本,代码如下 #find_package(OpenCV 3.3 REQUIRED) #如果不需要指定OpenCV版本,代码如下 find_package(OpenCV REQUIRED)#添加OpenCV头文件 includ…...
day57【动态规划】647.回文子串 516.最长回文子序列
文章目录 647. 回文子串516.最长回文子序列 647. 回文子串 力扣题目链接 代码随想录讲解 题意:给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的…...

分享vmware和Oracle VM VirtualBox虚拟机的区别,简述哪一个更适合我?
VMware和Oracle VM VirtualBox虚拟机的区别主要体现在以下几个方面: 首先两种软件的安装使用教程如下: 1:VMware ESXI 安装使用教程 2:Oracle VM VirtualBox安装使用教程 商业模式:VMware是一家商业公司,而…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...