数据结构与算法(仓颉版) 课件 全套 chap1 -15 数据结构与算法 - -排序_第1页
数据结构与算法(仓颉版) 课件 全套 chap1 -15 数据结构与算法 - -排序_第2页
数据结构与算法(仓颉版) 课件 全套 chap1 -15 数据结构与算法 - -排序_第3页
数据结构与算法(仓颉版) 课件 全套 chap1 -15 数据结构与算法 - -排序_第4页
数据结构与算法(仓颉版) 课件 全套 chap1 -15 数据结构与算法 - -排序_第5页
已阅读5页,还剩346页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数据结构与算法(仓颉版)

2第1章数据结构与算法第2章仓颉语言基础第3章仓颉语言数据类型第4章三大流程控制第5章函数第6章数据容器第7章泛型第8章面向对象基础第9章文件第10章异常处理第11章线性表第12章树和二叉树第13章图论第14章查找第15章排序目录软件和程序软件包括以下一些内容:(1)运行时,能够提供所要求功能和性能的指令或计算机程序集合。(2)程序能够满意地处理信息的数据结构(3)描述程序功能需求、程序如何操作和使用所要求的文档。程序设计语言软件包括以下一些内容:(1)运行时,能够提供所要求功能和性能的指令或计算机程序集合。(2)程序能够满意地处理信息的数据结构(3)描述程序功能需求、程序如何操作和使用所要求的文档。计算机组成(1)计算机硬件设备由存储器、运算器、控制器、输入设备和输出设备五个部分组成。(2)存储程序思想——把计算过程描述为由许多命令按一定顺序组成的程序,然后把程序和数据一起输入计算机,计算机对已存入的程序和数据处理后,输出结果。6程序设计著名计算机科学家沃思提出了一个公式:

程序=数据结构+算法。算法解决“如何操作数据?”的问题。数据结构是指定数据的类型和数据的组织形式,解决了“如何描述数据?”的问题。7程序设计过程分析问题算法与数据结构程序设计语言流程图数据结构数据结构是相互之间存在的一种或多种特定关系的数据元素的集合。数据结构中的“关系”是指数据间的逻辑关系,与数据的物理存储方式无关,同一种逻辑结构可以有多种不同物理存储方式。本章将详细介绍数据结构的几大分类:线形结构、树形结构和图(网状)结构。8数据结构在计算机领域中具有重要地位,是操作系统、人工智能、计算机组成原理、程序设计、软件工程、数据库、编译原理等课程的重要基础9算法找假币方法一:n-1次1012345678910?方法二:n/2次1112345679108方法三:log2N次12“算法”就是解决一个问题而采取的方法和步骤,是对解题方案的准确而完整的描述,是一系列解决问题的清晰指令。13五个属性(1)确定性。(2)可行性。(3)有穷性。(4)输入性。(5)输出性。14三个层次层次内容第一层一些基本的算法,如排序、查找、递归法等算法第二层涉及算法的时间复杂度和空间复杂度,如分治法、贪心算法、动态规划法等第三层涉及智能优化算法的学习,如遗传算法、蚁群算法、聚类算法等方法15算法复杂性空间复杂度时间复杂度16

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。(1)算法的输入输出数据所占用的存储空间由要解决的问题决定,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。(2)算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。(3)算法在运行过程中临时占用的存储空间随算法的不同而异。17

算法的时间复杂度是一个函数,通常用大O符号表述,用于定量描述了该算法的运行时间。

算法中模块n的基本操作的重复执行次数计为函数f(n),算法的时间复杂度为T(n)=O(f(n))。

常数阶O(1),对数阶O(log2n),线性阶O(n),线性对数阶O(nlog2n),平方阶O(n^2),立方阶O(n^3),...,k次方阶O(n^k),指数阶O(2^n)。18算法评价标准1.正确性2.可读性3.健壮性4.高效率与低存储量需求19算法效率减少程序复杂性(圈复杂度V(G))20选用等效的高效率算法例如:鸡兔问题方法1:利用二重循环来实现。方法2:利用一重循环来实现。方法3:21x+y=302x+4y=90X=(4a-b)/2Y=(b-2a)/2算法表示方式程序流程图N-S图伪语言22程序流程图23N-S图24伪语言25伪语言(Pseudocode)也称伪代码,介于自然语言和计算机语言之间,并不是真正存在的编程语言。伪代码综合使用多种编程语言中语法、保留字,甚至会用到自然语言,不采用图形符号,因此书写方便、格式紧凑,便于向计算机编程语言(Pascal,C,Java……)过渡。第2章仓颉语言基础

周元哲

机械工业出版社271仓颉语言简介

2仓颉语言在数据结构和算法优点

3CodeArtsIDEforCangjie

4VSCode+仓颉插件

5DevEcoStudio开发环境

6cjpm项目管理

28仓颉(Cangjie)是专为HarmonyOS生态量身定制的全场景智能应用编程语言,主打原生智能化、天生全场景、高性能、强安全。仓颉与ArkTS、C/C++共同构成鸿蒙的三大官方开发语言,ArkTS属于动态类型语言,基于TypeScript,易学易用,适合快速开发。仓颉属于静态类型语言,适应于性能与安全要求更高的场景。C/C++属于高性能计算、硬件加速等底层场景。29项目启动(2019年)华为于2019年正式启动仓颉编程语言项目,最初作为内部技术预研,旨在为鸿蒙生态构建原生的全场景智能开发语言。2.技术探索与命名(2020年)2020年项目正式命名为“仓颉”,寓意“造字”般开创中文编程新纪元。3.内部试点与商用验证(2022-2023年)2022年首次在华为自研的鸿蒙路由器上商用,替代原有Go模块,验证其在高并发场景下的性能优势。2023年起与国家电网、中航等头部企业合作,在金融、电信、政务等关键行业进行商业验证。304.正式发布(2024年)2024年6月21日,华为在开发者大会(HDC)上正式发布仓颉语言,并推出HarmonyOSNEXT开发者预览版,标志着其走向公开生态。5.开源与生态扩张(2025年起)2025年7月30日,华为宣布仓颉正式在GitCode平台开源,包括编译器、运行时和标准库。同年,已有超过1000个应用采用仓颉开发,20+高校开设相关课程,社区共建库达139个。6.未来规划(2025-2026年)华为计划推动仓颉跨平台兼容(Linux/Windows等),强化AI原生编程能力(如内置大模型API),并加入Apache基金会实现社区化治理。31仓颉语言的核心特点可概括为以下方面:1.多范式一体仓颉语言具有函数式、面向对象、命令式三种范式,而且可以自由混合。函数式:高阶函数、代数数据类型、模式匹配、不可变值语义,写“做什么”而非“怎么做”。面向对象:类/接口/继承/多态,模块化与数据封装。命令式:值类型、全局函数、for/while流程控制,算法直译。2.类型与内存双安全静态强类型+编译期类型推断:变量、函数签名在编译期锁定,拒绝隐式转换,把空指针、类型错用消灭在上线前。自动内存管理+运行时检查:数组越界、数值溢出、字符串编码不合法都会立即抛异常。

32仓颉语言的核心特点可概括为以下方面:

3.轻量级“用户态线程”并发协程级线程创建销毁开销微秒级;写法与普通函数一样,运行时自动调度。提供无锁或细粒度锁并发对象库,业务代码无需关心锁即可线程安全调用。4.与跨语言互操作仓颉可以编译为原生可执行文件,适合性能/边缘场景。仓颉可以编译成字节码,复用Java生态与调试工具链。仓颉与C/C++、ArkTS、JS、Rust等无缝互调。33仓颉语言的核心特点可概括为以下方面:

3.轻量级“用户态线程”并发协程级线程创建销毁开销微秒级;写法与普通函数一样,运行时自动调度。提供无锁或细粒度锁并发对象库,业务代码无需关心锁即可线程安全调用。4.与跨语言互操作仓颉可以编译为原生可执行文件,适合性能/边缘场景。仓颉可以编译成字节码,复用Java生态与调试工具链。仓颉与C/C++、ArkTS、JS、Rust等无缝互调。34版本类型更新周期适用场景获取方式稳定版

(STS)半年更新生产环境官网直接下载内测版

(Canary)每月更新体验新特性需申请内测权限鸿蒙版Beta测试鸿蒙应用开发DevEcoStudio插件35仓颉语言编辑器:1】CodeArtsIDEforCangjie2】VSCode+仓颉插件3】DevEcoStudio+仓颉插件

支持语法高亮、类型提示、跨语言调试、协程级可视化,实现创建工程、编译工程及运行验证等流程,并通过仓颉编译工具链进行仓颉程序构建与编译过程。36仓颉编程语言官方网站提供了仓颉软件开发工具包(softwaredevelopmentkit,SDK)和CodeArtsIDEforCangjie软件。仓颉SDK是开发仓颉程序的必备工具,CodeArtsIDEforCangjie软件能够完成Windows系统下的仓颉开发环境的搭建。3738atrs和.cache是CodeArts出于自身运作需要自动创建的,通常不用理会。cjpm.toml为项目管理核心配置文件,其内容描述了该项目的内部组成以及编译构建参数。cjpm.lock是自动生成,依赖锁定文件。src目录用于存储项目的全部程序文件。target目录用于存储程序文件的编译结果,包括可执行文件以及一些过程文件。394041第3章仓颉语言数据类型

周元哲

机械工业出版社431变量

2三种声明方式

3基本数据类型

4运算符

4.6运算符优先级

变量在程序中用来标识各种程序成分,命名程序中的一些实体。包括三方面:

1.字母;2.数字;

下划线:“_”

合法的标识符:x,a1,wang,num_1,radius不合法的标识符:first-name,5sum单击此处编辑母版文本样式第二级第三级第四级第五级(1)变量名可以由字母、下划线、中文组成。(2)变量名的第一个字符不能以数字开头。(3)尽量不要使用容易混淆的单个字符作为标识符,例如数字0和字母o,数据1和字母l等。(4)变量名不能和关键字同名。(5)推荐小驼峰(`userName`)或下划线(`user_name`)风格,保持项目一致。(6)避免单字母魔法值,做到“见名知义”。(7)区分大小写,a和A是两个不同的标识。单击此处编辑母版文本样式第二级第三级第四级第五级(1)简单变量和容器根据变量存储的内容多少,变量分为简单变量和数据容器。简单变量只能保存一个值,具有Int、Float、Bool、Rune、Unit等类型。数据容器可以存储多个值,具有string、enum、Tuple、Range、Array、struct、class、Arrylist、HashSet、HashMap等类型。本书采用简单变量和数据容器的分类进行讲解。单击此处编辑母版文本样式第二级第三级第四级第五级(2)不可变变量、可变变量和常量。

根据变量存储的内容是否可以发生改变,变量分为不可变变量、可变变量和常量。不可变变量指的是在变量被初始化(赋值)后,不能发生改变的变量。可变变量是指在变量被初始化后,可以发生改变的变量。常量就是不管在什么条件下,都不会改变的量。单击此处编辑母版文本样式第二级第三级第四级第五级(3)值类型和引用类型根据变量存储的内存空间不同,存储在栈还是堆,分为值类型(valuetype)和引用类型(referencetype)。值类型使用栈,具有Int、Float、Bool、Rune、Unit、enum、Tuple、struct等数据类型。引用类型使用堆,具有class、Array、Arrylist、HashSet、HashMap等数据类型。单击此处编辑母版文本样式第二级第三级第四级第五级不可变变量

初始化后值不可再修改,相当于密封盒子,具有编译期优化(常量折叠、内联),线程安全,无需同步机制和降低代码复杂度,提升可测试性等优点。

letage=25//类型推断为Int64letname:String="张三"//显式指定类型单击此处编辑母版文本样式第二级第三级第四级第五级可变变量变量(variable)可以存储一个特定类型的值。在程序运行过程中,变量的值可以随时修改。但类型一旦确定便不可变,用于循环计数器、累加器等需变更状态的场景。varscore=85//可重新赋值score=90varcount:Int64//先声明,后赋值count=10单击此处编辑母版文本样式第二级第三级第四级第五级常量的值必须显式制定,有编译器在编译时通过计算得到,在程序运行过程中不允许修改,适合数学常数、配置上限等全局不变量。constMAX_RETRIES=3//编译期求值,运行时不可改constPi:Float64=3.1415926单击此处编辑母版文本样式第二级第三级第四级第五级整型数据单击此处编辑母版文本样式第二级第三级第四级第五级整型数据根据前缀来区分各种进制数单击此处编辑母版文本样式第二级第三级第四级第五级实型数据例如:e-5,1.2E-5,1e单击此处编辑母版文本样式第二级第三级第四级第五级字符单击此处编辑母版文本样式第二级第三级第四级第五级布尔型数据运算符与表达式(1)算术运算符(+、–、*、/、**、%)。(2)关系运算符(>、<、>=、<=、==、!=)。(3)逻辑运算符(逻辑与(&&)、逻辑或(||)、逻辑非(!))。(4)位运算符(<<、>>、~、|、^、&)。(5)赋值运算符(=、复合赋值运算符)。运算符与表达式几个相关概念

目(操作数个数)

优先级

结合性表达式运算符与表达式1.算术运算符和算术表达式

运算符含义优先级+加法这些运算符的优先级相同,但比下面的运算符优先级低-减法*乘法这些运算符的优先级相同,但比上面的运算符优先级高/除法**幂运算%取模2.赋值运算符和赋值表达式赋值运算符赋值运算符用“=”表示。赋值表达式

变量=表达式等号的左边必须是变量,右边是表达式。运算符与表达式复合的赋值运算符赋值运算符“=”与7种算术运算符(+、-、*、/、**、%)构成复合的赋值运算符。例如:a+=3 等价于 a=a+3a*=a+3 等价于 a=a*(a+3)a%=3 等价于 a=a%3注意:“a*=a+3”与“a=a*a+3”是不等价的,“a*=a+3”等价于“a=a*(a+3)”,这里括号是必需的。运算符与表达式

关系运算符和关系表达式

运算符含义优先级结合性>大于这些运算符的优先级相同,但比下面的运算符优先级低左结合>=大于等于<小于这些运算符的优先级相同,但比上面的运算符优先级高<=小于等于==等于!=不等于运算符与表达式4.逻辑运算符和逻辑表达式

符号含义表达式说明&&与x&&y逻辑与。当且仅当x和y均为真时,运算结果为真,否则为假。||或x||y逻辑或。当x和y至少有一个为真时,运算结果为真,否则为假。!非!x逻辑非。如果x为真,则返回假;如果x为假,则返回真。第4章三大流程控制

周元哲

机械工业出版社651三种基本结构

2顺序结构

3分支结构

4循环概述

流程图的三种基本结构aABb顺序结构先执行A,

再执行B.若P为真,则执行A,

否则执行B.若P为真,则执行A,

否则跳过A.aAYNBpabAPNYb选择结构流程图的三种基本结构ApNY当型循环结构abApYNba直到型循环先执行A,再判断,若P为真,反复执行A,P为假时出循环。当P为真,反复执行A,P为假时出循环。N-S流程图去掉了箭头,算法写在一个矩形框里。它也有三种结构:顺序、选择和循环N-S结构流程图AB顺序结构pyesnoAB选择结构当p成立A当型循环A

当p成立直到型循环

任何程序均可以由“顺序”、“选择”和“循环”这三种基本结构通过有限次的组合与嵌套来描述。

任何程序设计语言均由这三种基本结构组成,其差别在于具体语法的形式不同,而原理是相同的。程序的基本结构1、顺序结构ABAB流程图N-S图2、选择结构分支选择结构3、循环结构当型循环直到型循环共同特点:单入口、单出口三种结构之间可以是顺序关系、平行关系,也可以互相嵌套,通过结构之间的复合形成复杂的关系。三种基本结构的特点流程图例1:求三个整数的和开始输出sum的值结束输入x,y,zsum=x+y+z输出sum的值sum=x+y+z输入x,y,zN-S结构流程图例1:求三个数中最小的那个数流程图N-S结构流程图开始输出min的值输入a,b,ca<bNmin=amin=bY结束min>cmin=cYNmin=bmin=aa<bYNmin=cmin>cYN输入a,b,c输出min的值输入语句仓颉语言使用readln()函数实现用户的输入。packagedemo3main(){

println("--------------------鹦鹉学舌---------------------")

print("你说我听:")

lets=readln()

print("你说的是:${s}")

return0}输出语句仓颉语言的标准输出通过print和println函数实现

packagedemo3main(){

print("不换行输出")

//类似Python的print(...,end="")

println("自动换行")

//类似Python的print()

//输出变量

letname="仓颉"

println(name)

//输出:仓颉

println("变量插值:${123}")

//字符串插值}单分支选择结构

if(条件){//条件为true时执行的代码块}expATFexpyesnoA//年龄大于18岁,输出自由出入该场所main():Int64{letage=18if(age>=18){println("您的年龄大于等于18,可以自由出入该场所")}return0}双分支选择结构if(条件){//条件为true时执行的代码块}else{//条件为false时执行的代码块}expABTFexpyesnoABmain():Int64{letscore=85if(score>=60){println("考试通过")}else{println("考试未通过")}return0}多分支选择结构ifexp1:

选择体1elifexp2:

选择体2……elifexpn:

选择体nelse:

选择体n+1exp1选择1TFexp2exp3选择n+1选择3选择2TTFF……main():Int64{letscore=85if(score>=90){println("优秀")}elseif(score>=80){println("良好")}elseif(score>=70){println("中等")}elseif(score>=60){println("及格")}else{println("不及格")}return0} 仓颉语言提供3种循环语句:while循环、do-while循环、for-in循环。while循环是以while开头,后跟循环条件,该条件必须是布尔类型的表达式,最后是“{}”包裹的循环体。do-while循环以do开头,后面紧跟“{}”包裹的循环体,然后是while结束,后面紧跟循环条件,该条件必须是布尔类型的表达式。for-in循环以for开头,之后跟以“()”包裹的循环条件,循环条件写法为“(循环变量in区间类型)”,最后是“{}”包裹的循环体。循环结构程序设计

循环结构程序设计的应用场合:当某个条件满足时,需要多次反复进行同样工作。例如:1、求实数x的10次方2、求数列1,2,…,i,…的前n项和3、判断一个整数是否是素数………………例:求1)问题分析:

sum,n=0,1n<=100sum=sum+nn=n+1YN输出sum结束开始sum=1+2+…+100

100个数

循环语句:循环变量初始化:循环控制条件:循环体:循环变量的修改:n=1n<=100sum+=nn=n+1while语句对于while语句的用法,要注意以下几点:(1)如果while后面表达式的值一开始就为假,则循环体一次也不执行。(2)循环体中的语句可以任意类型的语句。(3)遇到下列情况,退出while循环:

A表达式不成立

B循环体内遇到break、return语句。while语句——说明while语句之前必须预先设置判断的初始条件

防止“死循环”的发生在循环体中必须有使循环趋向结束的操作,即在循环体中要有能让逻辑表达式值改变的语句

正确使用缩进当循环体中含多条语句时,需用缩进这些多条语句,而且缩进一定要符合逻辑关系在循环体中,语句的先后位置必须符合逻辑否则会影响运算结果。packagedemo2main(){

letN=100

varcounter=1//表达式1,counter为循环变量

varsum=0

while(counter<=N){//表达式2,counter的变化范围从1到100

sum+=counter

counter+=1//表达式3,counter的步长为1

}

println("1到${N}之和为:${sum}")}dowhile循环也适用于循环体执行次数不确定的场景。do-while先执行再判断,while先判断再执行。如果至少需要执行一次循环体,用do-while;否则用while。dowhile循环语法如下所示:do{

循环体语句块}while(测试条件)packagedemo2import

std.convertmain():Int64{

print("请输入两个用逗号分隔的正整数:")

lets=readln()

lett=s.split(",")//将字符串s以逗号为分隔,拆分成字符串数组

varx=Int64.parse(t[0]);vary=Int64.parse(t[1])

varr=0

do{

print("gcd(${x},${y})=")

r=x%y;x=y;y=r

}while(r!=0)

print("${x}")

return0}for...in循环语句依次访问序列中全体元素,主要用于列表、元组、字符串等迭代结构。for语句书写格式如下:

for(循环变量in可迭代序列){

循环体}packagedemo3

main():Int64{

vars:Int64=0

for(iin1..=100){

//1..=100中的=号表明序列包含100

s+=i

}

print("1+2+3+...+99+100=${s}")

return0}循环嵌套

循环的嵌套,又称多层循环,应用于多个变量同时变化的情况。说明:1.外层循环可包含两个以上内循环

2.嵌套的循环的执行流程循环嵌套(1)外层循环和内层循环控制变量不能同名,以免造成混乱。(2)循环嵌套的缩进在逻辑上一定要注意,以保证逻辑上的重要性。(3)循环嵌套不能交叉,即在一个循环体内必须完整地包含另一个循环。循环控制语句

有时候我们需要在循环体中提前跳出循环,或者在某种条件满足时,不执行循环体中的某些语句而立即从头开始新的一轮循环,这时就要用到循环控制语句break、continue语句。一般格式

break功能

break语句用在循环体内,迫使所在循环立即终止,即跳出所在循环体,继续执行循环结构后面的语句。(1)break语句……break……expNY//用for语句判断从键盘上输入的整数是否为素数。packagedemo2importstd.convertmain():Int64

{

print("anumber:")

letline1=readln()

letnum=Int64.parse(line1)

varisPrime=true

//完全保留Python逻辑:循环2到num-2

for(iin2..num-1){

if(num%i==0){

isPrime=false

break

}

}

if(isPrime){

println("${num}isprime")

}else{

println("${num}isnotprime")

}

return0}一般格式

continue功能在循环语句中强行提前结束本次循环,

而不是终止循环。(2)continue语句……continue……expNYpackagedemo3funcisPrime(n:Int64):Bool{

if(n<=1){returnfalse}

for(iin2..=Int64(Float64(n)**0.5)){

if(n%i==0){

returnfalse

}

}

returntrue}

main():Int64{

println("找出100以内的全部质数:")

varfound=0

for(iin2..=100){

if(!isPrime(i)){

continue//其后语句被跳过,直接尝试下一轮循环

}

found++

print("${i},")

}

print("\n一共找到${found}个质数.")

return0}第5章函数周元哲

机械工业出版社1021函数概述

2实参与形参

3参数分类

4lambda表达式

5函数重载

6递归函数

7变量作用域

①程序结构清晰,可读性好。②减少重复编码的工作量。③可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。使用函数的好处概述

函数是一组实现某一特定功能的语句集合,是可以重复调用、功能相对独立完整的程序段。使用库函数应注意:1、函数功能2、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型用户自定义函数1.从用户的使用角度库函数(标准函数):由系统提供

在程序前导入该函数原型所在的模块函数分类

函数(function)是一切可复用逻辑的最小单元,仓颉使用关键字func来表示函数定义的开始,func之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型之间使用冒号分隔,函数体定义在一对花括号内。形式参数和实际参数形式参数:定义函数时函数名后面括号中的变量名实际参数:调用函数时函数名后面括号中对应的参数说明实参可以是常量、变量和表达式,但必须在函数调用之间有确定的值。形参与实参个数相同形参定义时编译系统并不为其分配存储空间,也无初值;只有在函数调用时,临时分配存储空间,接受来自实参的值;函数调用结束,内存空间释放。基本类型作为参数举例//定义了一个名为add的函数,其参数列表由两个Int64类型的参数a和b组成,函数返回值类型为Int64,函数体中将a和b相加并返回。packagedemo2funcadd(a:Int64,b:Int64):Int64{

returna+b}main():Int64{

letm=add(3,7)

println(m)

return0}引用类型作为参数举例funcmultiply(v:Array<Float64>,ratio:Float64):Array<Float64>{

for(iin0..v.size){

v[i]*=ratio

}

returnv}

main():Int64{

letprices=[10.1,5.7,4.68,9.98]

println("prices:${prices}")

letpricesReturned=multiply(prices,1.1)

println("pricesReturned:${pricesReturned}")

return0}非命名参数举例packagedemo1//非命名参数函数的调用

funcadd(a:Int64,b:Int64):Int64{

returna+b}main():Int64{

println(add(1,2))

return0}命名参数举例packagedemo1//命名参数函数的调用funcadd(a!:Int64,b!:Int64):Int64{

returna+b}

funcsum(a!:Int64=2,b!:Int64=3):Int64{

returna+b}main():Int64{

println(add(a:1,b:2))

println(sum())

println(sum(a:1,b:2))

return0}变长参数(variablelengtharguments)用于解决函数调用时实参个数不固定的问题//可变参数在最后,形参为数组Array<T>时,该形参数组接受多个类型为T的实参packagedemo1main():Int64{

myPrint("穿越宋朝必听金曲:","浣溪沙","西江月","满江红","点绛唇")

return0}funcmyPrint(title:String,contents:Array<String>){

println(title)

for(xincontents){

println("\t"+x)

}}lambda表达式就是“匿名函数”——没有名字、可以就地定义、就地调用、当做值传来传去。语法形式:

{p1:T1,...,pn:Tn=>expressions|declarations}。

其中,=>之前为参数列表,多个参数之间使用,分隔,每个参数名和参数类型之间使用:分隔。=>之前也可以没有参数。=>之后为lambda表达式体,是一组表达式或声明序列。Lambda表达式的参数名的作用域与函数的相同,为lambda表达式的函数体部分,其作用域级别可视为与lambda表达式的函数体内定义的变量等同。packagedemo1importstd.convertfuncgetOperation(op:String){

letdiv={a:Int64,b:Int64=>a/b}

if(op=="+"){{a:Int64,b:Int64=>a+b}}

elseif(op=="-"){{a:Int64,b:Int64=>a-b}}

elseif(op=="*"){{a:Int64,b:Int64=>a*b}}

else{div}}main():Int64{

print("请输入操作数1:")

leta=Int64.parse(readln())

print("请输入操作符(+-*/之一):")

letop=readln()

print("请输入操作数2:")

letb=Int64.parse(readln())

letr=getOperation(op)(a,b)

print("计算结果:${r}")

return0}有时同一种功能的函数,有多种实现方式。在同一作用域中,定义了多个函数,这些函数有以下特点:1.函数名相同;2.函数参数类型不同;3.函数参数个数不同;就把这些函数称为:函数重载packagedemo1funcadd(x:Int64,y:Int64){

returnx+y}funcadd(x:Float64,y:Float64){

returnx+y}//如果是改变函数参数的变量名,则不算函数重载。funcadd(x:Int64){

returnx+1}main():Int64{

println(add(2,4))

println(add(1.8,4.2))

println(add(5))

return0}函数的递归调用

在函数的执行过程中又直接或间接调用该函数本身

直接递归调用

在函数中直接调用函数本身间接递归调用

在函数中调用其它函数,其它函数又调用原函数f()调f调f2调f1f1()f2()defa(x):……

z=b(y)…….return(2*z)defb(t):……

m=a(x)…….return(3+c)deff(x):……

z=f(y)…….return(2*z)递归算法的两个基本特征递推归纳将问题转化为比原问题小的同类规模,归纳出一般递推公式.

故所处理的对象要有规律地递增或递减递归终止当规模小到一定的程度应该结束递归调用,逐层返回常用条件语句来控制何时结束递归总结执行过程(两个阶段)第一阶段:逐层调用,调用函数自身第二阶段:逐层返回,返回到调用该层的位置递归调用是多重嵌套调用的一种特殊情况调用的深度:调用的层数

设计递归算法的方法前提:原问题可以层层分解为类似的子问题,且子问题比原问题规模更小规模最小的问题具有直接解方法:寻找分解方法:将原问题转化为子问题求解,例:n!=n*(n-1)!设计递归出口:根据规模最小的子问题确定递归终止条件,例:求解n!,当n=0时,n!=1;11十一月2026例:汉诺塔问题。设有三座塔座(A、B、C),在一个塔座(设为A)上有64个盘片,盘片不等,按大盘在下,小盘在上的顺序依次叠放。现要将A塔上的盘片借助于B塔,移到C塔上并保持同样顺序叠排,移动盘片时必须遵守以下规则:(1)每次只能移动一个圆盘;(2)圆盘可以插在A、B、C任意一个塔座上;(3)任何时候都不能将一个较大的圆盘放到较小的圆盘之上。11十一月2026

将A塔上的红、黄两盘移动到B上蓝盘放到C上将红、黄两盘从B移动到C盘上。(完成)ABC问题分析:(1)n=1时,直接将其从A->C;(2)n>1时,只要先将前n-1个借助C从A->B,那么可以把第n个直接从A->C;(3)如何将剩下的n-1个圆盘遵守规则借助A从B->C,问题性质同(2);问题性质相同,因此适合采用递归过程!若将n个盘片按规定从A塔移至C塔,移动步骤可分为三步:把A塔上的n-1个盘片借助C移动到B塔把第n个盘片从A塔移至C塔把B塔上的n-1个盘片借助A塔移至C塔算法用函数hanoi(n,x,y,z)以递归算法实现11十一月2026盘片数源塔借用塔目标塔

递归终止:当递归调用到盘片数为1时算法描述:1)递归调用hanoi(n-1,a,c,b)2)将n号盘片从a塔移动到c塔3)递归调用hanoi(n-1,b,a,c)importstd.collection.ArrayList

varsteps=ArrayList<String>()

//可增删元素的字符串数组funchanoi(n:Int64,a:String,b:String,c:String):Unit{

if(n==1){

steps.add(a+"-->"+c)

//1个盘,从a移至c

}

else{

hanoi(n-1,a,c,b)

//将n-1个盘从a移至b,以c为中转

steps.add(a+"-->"+c)

//将a上的大盘移至c

hanoi(n-1,b,a,c)

//将n-1个盘从b移至c,以a为中转

}}

main():Int64{

hanoi(5,"A","B","C")

println("移盘总次数:${steps.size}")

print(steps)

return0}变量的作用域当程序中有多个函数时,定义的每个变量只能在一定的范围内访问,称之为变量的作用域。按作用域划分,将变量分为局部变量和全局变量。1.局部变量

在一个函数内或者语句块内定义的变量称为局部变量。局部变量的作用域仅限于定义它的函数体或语句块中。packagedemo1main():Int64{//模板字符串的局部作用域vara=3;varb=4println("${a}\t${b}")

//分支结构的局部作用域if(true){letnum=5println(num)}return0}2.全局变量

在所有函数之外定义的变量称为全局变量,它可以在多个函数中被引用。packagedemo1varnum=2funcfun1(){

num++

returnnum}funcfun2(){

num--

returnnum}main():Int64{

println(num)

println(fun1())

println(fun2())

return0}第6章数据容器

周元哲

机械工业出版社1301数据容器简介

2字符串类型

3枚举

4元组类型 5区间类型 6数组类型7结构体8ArrayList 9HashMap 10HashSet 11值类型和引用类型

131在仓颉编程语言中,容器主要指数据结构容器,内置了完整的集合类型族,借鉴了Java和Kotlin的优秀实践并针对鸿蒙生态优化。数据容器可以存储多个值,具有string、enum、Tuple、Range、Array、struct、class、Arrylist、HashSet、HashMap等类型。132String是字符串类型,用于表示文本序列,是不可变的引用类型。字符串分为2种形式:单行字符串和多行字符串。

lets1:String="你好"

//字符串

//多行字符串(三个双引号)lets2:String="""第一行//须另起一行第二行第三行"""133字符串可以视为由字符(Rune)构成的序列packagedemo2main():Int64{

lets:String='IloveCangjie'

leta:Array<Rune>=s.toRuneArray()

println("a.size=${a.size}")

print(a)

return0}134成员函数描述s.toAsciiLower()生成并返回字符串s的副本,字符皆为小写形式。s.toAsciiUpper()生成并返回字符串s的副本,字符皆为大写形式。s.endsWith(x)判断字符串s是否以字符串x结尾,返回布尔型。s.startsWith(x)判断字符串s是否以字符串x开头,返回布尔型。s.count(x)统计字符串s中子串x的出现次数。s.indexOf(x)在字符串s中查找并返回子串x的位置。s.trimEnd(x)生成并返回字符串s的副本,该副本已去除尾部连续的x。s.replace(x,y)生成并返回字符串s的副本,该副本中所有的子串x替换成y。s.split(x)以x为间隔,将字符串s切分成多个子串,以数组形式返回。135enumColor{Red|Green|Blue}Color具有3个构造器:Red、Green和Blue,分别表示RGB色彩模式中的红色、绿色和蓝色。136元组(Tuple)可以将多个不同的类型组合在一起,成为一个新的类型。元组类型使用(T1,T2,...,TN)表示,其中T1到TN可以是任意类型,不同类型间使用逗号(,)连接。元组至少是二元,例如,(Int64,Float64)表示一个二元组类型,(Int64,Float64,String)表示一个三元组类型。元组的长度是固定的,即一旦定义了一个元组类型的实例,它的长度不能再被更改。元组类型是不可变类型,即一旦定义了一个元组类型的实例,它的内容不能再被更新。137main():Int64{

letx:(Int64,Float64)=(3,3.141592)

println("${x[0]}\t${x[1]}")

lety:(Int64,Float64,String)=(3,3.141592,"PI")

println("${y[0]}\t${y[1]}\t${y[2]}")

return0}138main():Int64{

//1.构造三元组

lett=('601857','中国石油',13872.99)

//2.解构:左边变量必须带类型

let(x,y,z)=t

//3.打印

println("x=${x},y=${y},z=${z}")

//输出:x=601857,y=中国石油,z=13872.99

vara=11;varb=99

println("a=${a},b=${b}")

(a,b)=(b,a)

//交换a和b

print("a=${a},b=${b}")

return0}元组解构139

区间类型用于表示有固定步长的数值序列,用Range<T>标识。

每个区间类型的实例都会包含start、end和step三个值。其中,start和end分别表示序列的起始值和终止值,step表示序列中前后两个元素之间的差值(即步长);start和end的类型相同(即T被实例化的类型),step类型是Int64,并且它的值不能等于0。区间140letr1=0..10:1

//

左闭右开[0,10],包含0-9

letr2=0..=10:1

//左闭右闭

[0,10],包含0-10

letr3=10..0:-2

//递减区间,包含10,8,6,4,2区间141容器是一种特殊的对象,用于保存多个相同类型元素的对象,多个元素相互之间存在次序关系。创建数组时需指定固定长度且不可变,适合处理大小已知不变的数据集合;数组的定义语法如下:Array<T>需要在Array关键后后面的<>内指明数组所容纳的元素类型。数组142结构体是仓颉语言中一种重要的值类型复合数据结构,struct类型的定义以关键字struct开头,后跟struct的名字,接着是定义在一对花括号中的struct定义体。struct语法基本格式如下所示:struct结构体名称{//主构造函数同时定义并初始化成员变量//成员变量//构造函数//成员函数}结构体143在仓颉语言里,ArrayList<T>是一个泛型动态数组,用于存储相同数据类型的有序序列的数据,许多特性和Array一样,唯一不同的是,ArrayList允许新增和删除操作。ArrayList144importstd.collection.*//只能存放T类型元素,不同T之间不可互转varlist:ArrayList<String>=ArrayList<String>()packagedemo3importstd.collection.ArrayList

//导入ArrayList类型main():Int64{

leta=ArrayList<String>()

//空动态数组

println("a=${a},a.size=${a.size},a.capacity=${a.capacity}")

letb=ArrayList<String>(64)

//预留64个元素存储空间的空动态数组

println("b=${b},b.size=${b.size},b.capacity=${b.capacity}")

lett:Array<Int64>=[1,2,3]

//包含3个元素的数组

letc=ArrayList<Int64>(t)

//从数组复制构建动态数组

println("c=${c},c.size=${c.size},c.capacity=${c.capacity}")

letd=ArrayList<Int64>(5,{i:Int64=>i*i})//含5个元素,值由匿名函数计算而得

print("d=${d},d.size=${d.size},d.capacity=${d.capacity}")

return0}ArrayList145

特性Array<T>ArrayList<T>长度固定不可变动态可扩容内存开销较小,无额外空间较大,预留扩容空间性能访问快,无扩容开销插入删除灵活,可能触发扩容适用场景大小已知的数据集大小不确定的动态数据线程安全需手动同步提供并发版本增删元素❌不可✅原地增删146HashMap<K,V>是一种基于哈希表实现的键值对集合类型,提供对其包含的元素的快速访问。HashMap<K,V>中的每个元素都使用其键作为标识,通过使用键来访问相应的值,核心特性如下所示:快速访问:通过键的哈希值直接定位元素,平均时间复杂度为O(1)键唯一性:不允许重复的键,重复键会覆盖旧值无序性:不保证按插入顺序遍历元素HashMap<K,V>

147HashSet集合用来存储相同数据类型的无序序列且元素不重复的数据。HashSet基于哈希表实现,提供O(1)时间复杂度的查找、添加和删除操作。HashSet<T>具有如下特性:1.元素唯一性:动拒绝重复值,返回bool提示是否成功2.无序存储:不保证插入顺序,不支持下标访问3.高效查找:Contains方法接近O(1)复杂度4.集合运算:内置并集、交集、差集等操作5.动态扩容:自动调整容量,可指定初始容量HashSet148packagedemo2main():Int64{

letc:Float64=1.1

vard=c

d=7.7

println("c=${c},d=${d}")

return0}值类型

栈是操作系统分配给应用程序独享的内存空间,栈的容量通常较小,一般在几兆字节及几十兆字节之间。值类型的对象通常分配于栈空间,对象复制时会建立完全独立的副本。d是独立于c的复制品。149packagedemo2main():Int64{

leta:Array<String>=['枯藤','老树','青蛙']

letb=a

b[2]='昏鸦'

println("a=${a}")

println("b=${b}")

}引用类型

堆是计算机上的公共存储空间,其容量较大。引用类型的对象实体通常存储于堆空间,通过栈空间的引用对堆内实体进行访问。当引用类型的对象被复制时,只是复制了引用而非实体,多个变量指向同一个实体。某一个变量的改变,导致实体的改变,必将引起其他变量的内容变化。数组是引用类型,操作的结果是a、b两个变量事实上引用了同一个位于堆内的数组对象实体,所以,对b[2]的修改也导致了a[2]的变化。第7章泛型周元哲

机械工业出版社1511泛型概述

2泛型函数

3泛型结构体

4泛型类

泛型接口

6std.collection包

152泛型(Generics)是仓颉语言中一种类型参数化机制,是指一个在声明时未知并且需要在使用时指定的类型。泛型允许在定义类、接口、函数时推迟类型指定,直到使用时才传入具体类型,从而操作不同类型的数据而无需重复编写代码,实现一套代码处理多种数据类型的能力。泛型的本质是将类型作为参数传递给代码模板,编译器根据传入的类型自动生成专用版本。仓颉语言的泛型系统结合了Java的类型安全和C#的语法简洁性,同时通过保留运行时类型信息避免了Java的类型擦除问题。1531.代码复用:一份代码可适配多种数据类型,避免重复开发。例如,泛型排序函数可同时处理整数、字符串、图算法中的Edge(按权重排序)等,无需为每种类型单独写排序逻辑。2.类型安全:编译时进行类型校验,避免运行时类型转换错误。相比使用Any类型(无类型校验),泛型能确保传入的类型与预期一致(如ArrayList<Edge>明确存储边对象)。3.性能优化:无需装箱/拆箱操作(值类型与引用类型的转换),保持原生类型的执行效率。例如,泛型Stack<Int64>直接存储整数,比Stack<Any>减少类型转换开销。4.扩展性强:支持自定义类型适配。例如,图算法中的Node类可通过泛型支持不同类型的距离(Int64/Double),无需修改算法核心逻辑。优点154在声明全局泛型函数时,只需要在函数名后使用尖括号声明类型形参,然后就可以在函数形参、返回类型及函数体中对这一类型形参进行引用。func函数名<T>(参数:T)->返回值类型{//逻辑实现(依赖T的特性或与类型无关)}参数说明:<T>:类型参数声明(T是占位符,可自定义名称如<Element>

<Weight>)。调用时需显式指定类型(或由编译器自动推导)。全局泛型函数155局部泛型函数定义在其他函数/方法内部的泛型函数,仅在内部作用域可见,通常用于辅助外部函数实现复杂逻辑(如算法内部的比较、转换)。局部泛型函数156结构体中引入类型参数,使得结构体可存储/处理多种类型的数据,同时保持结构逻辑一致。适用于定义容器(如栈、队列)、数据模型(如键值对)等通用结构。

泛型结构体语法如下所示:struct结构体名<T>{var成员变量:T//泛型成员func方法名()->T{//实现逻辑}}

参数说明:关键字struct的结构体名之后,将类型形参用<>括起,多个类型形参使用“,”分离。泛型结构体157类中引入类型参数,支持继承、多态,且泛型类的子类可保留或约束父类的类型参数。适用于定义复杂的通用组件(如算法类、数据结构类),例如将图算法改造为泛型类,支持不同类型的权重(Int64/Double)。

泛型类语法如下所示:class类名<T>{var成员变量:Tinit(参数:T){self.成员变量=参数}func方法名()->T{...}}参数说明如下:关键字class的类名之后,将类型形参用<>括起,多个类型形参使用“,”分离。泛型类158接口(协议)中引入类型参数,定义泛型行为规范,实现类需指定具体类型或保留泛型参数。适用于定义通用能力(如容器的增删查、图的边操作),让不同实现类遵循统一规范。

泛型接口语法interface接口名<T>{func方法名(_element:T):Unitfunc获取方法()->T?}泛型接口159std.collection.forEach是仓颉语言标准库中为集合类提供的统一遍历方法,用于对集合中每个元素执行指定操作。packagedemo1importstd.collection.forEachfuncdisplay(e:String){print("${e},")}main():Int64{

letmasters=['柳宗元','韩愈','欧阳修','苏洵','苏轼','苏辙','王安石','曾巩']//方法1:print("唐宋八大家,Round1:")forEach(display)(masters)//方法2:

print("\n唐宋八大家,Round2:")

letop=forEach<String>(display)op(masters)//方法3:

print("\n唐宋八大家,Round3:")

masters|>forEach(display)

return0}160filter<T>用于对容器元素进行筛选,仓颉文档中filter<T>函数声明如下:public

func

filter<T>(predicate:(T)->Bool):(Iterable<T>)->Iterator<T>

packagedemo1import

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论