Microsoft Word - 第2章 线性表.docx

Size: px
Start display at page:

Download "Microsoft Word - 第2章 线性表.docx"

Transcription

1 第 2 章线性表 学习目标 u 理解顺序表的逻辑与存储原理, 并能实现简单顺序表 u 掌握单链表的逻辑与存储原理, 并能实现单链表 u 掌握双向链表的逻辑与存储原理 u 掌握循环链表的逻辑与存储原理线性表, 顾名思义是像线一样性质的表, 它的用处多不胜数, 是最常用且最简单的一种数据结构, 例如, 一串英文字母 一队手拉手的小朋友 一份学生成绩单等等都可以用线性表表示 线性表的存储结构有顺序存储结构和链式存储结构两种, 本章分别基于这两种存储结构来讲解常用的几个线性表 2.1 什么是线性表 线性表是具有相同特性的数据元素组成的一个有限序列 例如, 定义一个线性表来存储本班学生的学生编号, 可表示为如下形式 : (001, 002, ) 这就是一个线性表 线性表也可以用一个标识符来命名, 如 A = (001, 002, ) 线性表中元素的个数为线性表的长度, 当元素个数为 0 时, 称该线性表为空表 线性表中的元素可以是整数 字符等简单数据, 也可以由数个数据项组成 如第一章中的图 1-1, 它也是一个线性表, 描述的是新学期入学学生的信息, 其中每一个元素都由几个数据项组成, 在这种情况下, 常把元素称为一条记录 每一种数据结构都有它自己的特征, 线性表作为一种最简单的数据结构, 有如下几个特征 : (1) 线性表中有且只有一个开始结点 ( 头结点 ), 这个开始结点没有前驱结点 (2) 线性表中有且只有一个末尾结点 ( 尾结点 ), 这个末尾结点没有后继结点 (3) 除去开始结点与末尾结点, 其它结点都有一个前驱结点和一个后继结点 线性表的这种结构使元素逐个排列开来, 如手拉手的小朋友, 如此呈现给人们的数据形式就比较清晰明了 线性表在存储结构上有顺序存储和链式存储两种方式, 但不管哪种存储方式, 它们的结构都有如下特点 : l 均匀性 : 虽然不同数据表的数据元素可以是各种各样的, 但对于同一个线性表来说, 数据元素必须具有相同的数据类型和长度 l 有序性 : 各数据元素在线性表中的位置只取决于它们的序号, 数据元素之间的相对位置是线性的, 即存在唯一的 第一个 和 最后一个 数据元素, 除了第一个和最后一个外, 其它元素前面均只有一个数据元素 ( 直接前驱 ), 后面均只有一个数据元素 ( 直接后继 ) 数据结构的目的是和算法结合, 实现各种操作 线性表是一种比较灵活的数据结构, 它

2 的长度可根据需要增减, 它也可以进行插入 删除等操作 可对线性表进行的基本操作如下所示 : l 创建 -Create(): 创建一个新的线性表 l 初始化 -Init(): 初始化操作, 将新创建的线性表初始化为空 l 获取长度 -GetLength(): 获取线性表的长度 l 判断表是否为空 IsEmpty(): 判断线性表是否为空 l 获取元素 -Get(): 获取线性表某一个位置上的元素 l 插入 -Insert(): 在线性表的某一个位置插入一个元素 l 删除 -Delete(): 删除某一个位置上的元素 l 清空表 -Clear(): 清空线性表, 将线性表置为空 当然, 在设计线性表时, 也可以有其他操作, 例如, 根据某个条件对线性表中的元素进行排序 将两个线性表合并成一个 重新复制一个线性表等, 上面只是描述了线性表一些最基本的操作 线性表是应用最广泛的一种数据结构, 在使用过程中, 除了链表 栈和队列等, 线性表还有很多推广应用, 如时间表 排序表等 当然, 这些推广应用需要读者在实际开发中去深入学习, 限于教材篇幅, 本书只讲解最基础的线性表 2.2 线性表的顺序存储 ( 顺序表 ) 通过前面的学习可以知道, 线性表有顺序存储与链式存储两种结构, 它们各有自己的存 储特点, 在实现上也有所不同 本节先来学习一下线性表的顺序存储 顺序存储的原理 第一章简单讲解了线性表的顺序存储结构, 读者应对线性表的顺序存储结构原理已有所了解 所谓顺序存储, 就是在存储器中分配一段连续的存储空间, 逻辑上相邻的数据元素其物理存储地址也是相邻的 假如要用顺序表来存储四个字母, 则需要在内存中分配四个连续的存储单元, 如图 2-1 所示 图 2-1 顺序存储结构在图 2-1 中, 要存储的四个字母被存储在一段连续的存储空间中 由存储空间的地址可以看出, 这四个存储单元是连续的, 第一个存储单元由序号 0 来标记, 接下来的存储单元依次递增标记序号, 这样在查找元素时, 只要找到相应的索引就能找到元素, 非常方便 线性表的这种存储方式称为顺序存储或顺序映射, 又由于逻辑上相邻的两个元素在对应的顺序表中的存储位置也相邻, 因此这种映射也称为直接映射

3 在图 2-1 中, 我们分配了四个存储单元来存储这四个字符, 表的长度为 4, 容量也为 4 但要注意的是, 表的长度未必与容量相同 表的长度要小于等于表的容量, 因为可能申请了四个存储单元, 但只存入 3 个元素 在顺序存储中, 只要确定了线性表在存储空间里的起始位置, 线性表中任意元素就都可随机存取, 所以线性表的顺序存储结构是一种随机存取的结构 在高级语言中, 顺序存储是用数组来实现的 在顺序存储中, 系统不需要为表元素之间的逻辑关系增加额外的存储空间, 而且在存取元素时, 它可以根据给出的下标快速计算出元素的存储地址, 从而达到随机读取的目的 例如在图 2-1 中, 如果要读取第 3 个元素, 因它的下标为 2( 与第 1 个元素之间有两个间隔 ), 由内存段的起始地址和元素相差个数可以快速计算出第 3 个元素的存储地址 (0x *2 = 0x003), 计算出地址后, 就可以方便地对数据进行操作 但是, 如果在顺序表中插入或删除元素, 效率会特别低 对插入来说, 只限于在表的长度小于表的容量的顺序表中, 如果插入大量数据, 很难保证空间是否充足 而且一旦分配了存储空间, 如果想要扩充容量, 需要重新分配空间, 然后将原来的数据复制到新的空间中, 非常麻烦 另一方面, 即使空间充足, 那么在插入位置之后的元素必须都要向后移动, 这个效率非常低 同理, 如果要删除大量元素, 那么势必会造成空间的浪费, 而且删除元素后, 后面的元素都要向前移动, 效率也会非常低 顺序存储的实现 了解了顺序表, 那么我们接下来实现一个顺序表, 并完成其查找 插入和删除等基本操作 在实现各种数据结构时, 本书都以 C 语言为例 1 创建顺序表在创建顺序表时, 需要先创建一个头结点来存放顺序表的长度 大小和地址等信息, 然后再创建顺序表, 同时将顺序表的地址保存在头结点中, 其示意图如图 2-2 所示 图 2-2 顺序表示意图实现思路如下 : (1) 定义一个 struct 来保存顺序表信息 (2) 为头结点分配空间 (3) 为顺序表分配空间, 将顺序表空间地址保存在头结点中 (4) 将头结点地址返回给调用者 代码实现如下 : typedef struct _tag_seqlist // 头结点, 记录表的信息 int capacity; // 表容量 int length; // 表长度 int * node; //node[capacity], 为指针数组 TSeqList;

4 // 创建顺序表 SeqList* SeqList_Create(int capacity) // 返回值为 SeqList* 类型, 即顺序表的地址 int ret; TSeqList *temp = NULL; temp = (TSeqList*)malloc(sizeof(TSeqList)); // 为头结点分配空间 if (temp == NULL) ret = 1; printf("func SeqList_Create() error:%d\n", ret); return NULL; memset(temp, 0, sizeof(tseqlist)); temp->capacity = capacity; temp->length = 0; temp->node = (int*)malloc(sizeof(void*)*capacity); // 分配一个指针数组 if (temp->node == NULL) ret = 2; printf("func SeqList_Create() error:%d\n", ret); return NULL; return temp; // 将分配好的顺序表的地址返回 顺序表的实现并不难, 而且实现方式也有多种, 只要思路清晰, 代码实现就很简单, 读者也可以试着自己来实现一遍 2 求顺序表容量在实现顺序表时, 一般将顺序表信息保存在头结点中, 因此求顺序表容量时, 可以直接从头结点中获取 代码实现如下所示 : // 求顺序表容量 int SeqList_Capacity(SeqList* list) // 参数为顺序表地址 TSeqList *temp = NULL; if (list == NULL) // 作健壮性判断 return; temp = (TSeqList *)list; return temp->capacity; 3 求顺序表长度和求顺序表的容量一样, 求顺序表大小也是从头结点中获取信息, 代码如下所示 :

5 // 获取顺序表长度 int SeqList_Length(SeqList* list) TSeqList *temp = NULL; if (list == NULL) return; temp = (TSeqList *)list; return temp->length; 4 插入元素增删改查是数据结构的核心操作, 每种数据结构都要实现这几种最基本的操作 在顺序表中, 要插入元素, 则需要将插入位置后的所有元素向后移动, 其示意图如图 2-3 所示 图 2-3 插入元素在图 2-3 中, 要在顺序表的 1 角标位置插入元素 X, 则在插入时, 需要将 1 角标和其后的元素都向后移动一个单元, 其过程如图 2-4 所示 图 2-4 插入元素 X 图 2-3 和图 2-4 演示了往顺序表中插入元素的过程 在插入过程中, 需要考虑一些异常情况 :

6 l 当顺序表已满时, 表中的元素无法向后移动, 需要作出特别处理 ( 例如不插入, 或者新开辟一块更大的空间来存储这些元素 ) l 当插入的位置在空闲区域时, 需要作出相应处理 : 在空闲位置插入元素, 如图 2-5 所示 图 2-5 在空闲区域插入元素在图 2-5 中, 容量为 5 的顺序表中只有两个元素, 当插入新元素 X 时, 指定的位置是角标 3 的位置, 这样就造成元素不连续, 不符合顺序表的存储规则 在这种情况下可以作适当的修正, 将插入位置改为角标 2 有了插入元素的思路后, 接下来用代码来实现, 代码如下 : // 插入元素 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) // 参数为顺序表地址, 要插入的元素地址, 插入位置 int i; TSeqList *temp = NULL; // 先作健壮性判断 if (list == NULL node == NULL) // 如果顺序表为空, 或者结点为空 return -1; temp = (TSeqList *)list; // 如果顺序表已满 if (temp->length >= temp->capacity) return -2; // 容错 if (pos > temp->length) // 如果给出的 pos 在长度后, 即中间有空余, pos = temp->length; // 就修正到最后一个元素后面 for (i = temp->length; i > pos; i--) // 将插入位置的元素依次后移动 temp->node[i] = temp->node[i - 1]; temp->node[i] = (int)node; // 然后在腾出的位置插入新元素结点 temp->length++; // 插入成功后, 长度加 1 return 0; 5 删除元素

7 从顺序表中删除某一个元素, 则将元素删除后, 需要将后面的元素依次向前移动来补齐 空位, 删除过程如图 2-6 所示 图 2-6 删除元素删除过程相对来说没有插入过程那么复杂, 不必考虑内存不足时的 溢出 问题, 但因为要移动元素, 效率还是较低的 其代码实现如下所示 : // 删除元素 SeqList* SeqList_Delete(SeqList* list, int pos) int i; // 先作健壮性判断 TSeqList * tlist = NULL; SeqListNode * temp = NULL; tlist = (TSeqList *)list; if (list == NULL pos < 0 pos >= tlist->capacity) printf("seqlist_delete() error\n"); return NULL; temp = (SeqListNode *)tlist->node[pos]; // 要删除的元素 for (i = pos + 1; i < tlist->length; i++) // 将删除元素之后的所有元素前移 tlist->node[i - 1] = tlist->node[i]; tlist->length--; return temp; // 删除元素后, 长度要减 6 查找某个位置上的元素 在顺序表中查找某个元素是非常方便的, 因为顺序表在底层是以数组来实现的, 每个存

8 储单元都有索引标注, 要查找某个位置上的元素, 直接按索引来查找就可以 查找元素的代码实现如下所示 : SeqList* SeqList_Get(SeqList* list, int pos) // 先作健壮性判断 TSeqList * tlist = NULL; SeqListNode * temp = NULL; tlist = (TSeqList *)list; if (list == NULL pos < 0 pos >= tlist->capacity) printf("seqlist_get() error\n"); return NULL; temp = (SeqListNode *)tlist->node[pos]; // 将表中 pos 位置的结点指针赋给 temp return temp; 7 清空表清空顺序表是将表中的内容全部置为 0 其代码实现如下所示: // 清空顺序表 void SeqList_Clear(SeqList* list) TSeqList *temp = NULL; if (list == NULL) return; temp = (TSeqList *)list; temp->length = 0; memset(temp->node, 0, (temp->capacity*sizeof(void*)));// 将顺序表全部归 0 return; 8 销毁表销毁顺序表是将表整个销毁, 无法再进行使用 其代码实现如下所示 : // 销毁顺序表 void SeqList_Destory(SeqList* list) TSeqList* temp = NULL; if (list == NULL) // 如果参数顺序表为空 return; temp = (TSeqList *)list; if (temp->node!= NULL)

9 free(temp->node); // 先释放头结点中的指针数组 free(temp); // 再释放头结点 return; 至此, 已经实现了一个顺序表最基本的操作, 可以完成简单的增删改查的功能 接下来 可以用测试程序来测试一下这个顺序表的使用情况 注意 : 本书同系列教材 C 语言程序设计教程 C++ 程序设计教程 均使用 Visual Studio2013 来开发, 同样, 在本书中仍然使用 Visual Studio2013 作为数据结构的开发环 境, 关于 Visual Studio2013 的安装与使用, 请参考 C 语言程序设计教程 一书 ( 传智播 客高教产品研发部著 ), 本书不再重复叙述 在上述讲解中, 每一个函数都已实现, 因此在本例中, 只添加头文件 SeqList.h 与测试 程序 main.c 两个文件, 而函数实现代码的 SeqList.c 文件, 本例中不再重复给出, 具体如例 2-1 所示 例 2-1 SeqList.h // 头文件 1 #ifndef _SEQLIST_H_ 2 #define _SEQLIST_H_ 3 4 typedef void SeqList; 5 typedef void SeqListNode; 6 7 SeqList* SeqList_Create(int capacity); // 创建顺序表 8 void SeqList_Destory(SeqList* list); // 销毁顺序表 9 void SeqList_Clear(SeqList* list); // 清空线性表 10 int SeqList_Length(SeqList* list); // 获取顺序表长度 11 int SeqList_Capacity(SeqList* list); // 获取顺序表容量 12 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); // 插入元素 13 SeqList* SeqList_Get(SeqList* list, int pos); // 获取 pos 位置上的元素 14 SeqList* SeqList_Delete(SeqList* list, int pos); // 删除 pos 位置的元素 #endif main.c // 测试程序的文件 17 #include "SeqList.h" 18 #include <stdio.h> 19 #include <stdlib.h> typedef struct _Teacher char name[32]; 24 int age; 25 Teacher; 26

10 27 int main() int ret = 0; 30 SeqList * list = NULL; 31 Teacher t1, t2, t3, t4, t5; // 结点元素 32 t1.age = 31; 33 t2.age = 32; 34 t3.age = 33; 35 t4.age = 34; 36 t5.age = 35; 37 // 创建结点 38 list = SeqList_Create(10); // 创建顺序表 // 插入结点 41 ret = SeqList_Insert(list, (SeqListNode*)&t1,0); // 位置 0: 始终在头部插入 42 ret = SeqList_Insert(list, (SeqListNode*)&t2, 0); 43 ret = SeqList_Insert(list, (SeqListNode*)&t3, 0); 44 ret = SeqList_Insert(list, (SeqListNode*)&t4, 0); 45 ret = SeqList_Insert(list, (SeqListNode*)&t5, 0); printf(" 顺序表容量 :%d\n", SeqList_Capacity(list)); 48 printf(" 顺序表长度 :%d\n", SeqList_Length(list)); // 遍历顺序表 51 printf(" 遍历顺序表 :\n"); 52 for (int i = 0; i < SeqList_Length(list); i++) Teacher* temp = (Teacher*)SeqList_Get(list, i); // 获取链表结点 55 if (temp == NULL) printf("func SeqList_Get() error\n", ret); 58 return; printf("age: %d\n", temp->age); // 销毁链表 65 printf(" 销毁顺序表时 :\n"); 66 while (SeqList_Length(list) > 0) Teacher* temp = (Teacher *)SeqList_Delete(list, 0); // 删除头部元素 69 if (temp == NULL) 70

11 71 printf("func SeqList_Get() error\n", ret); 72 return; printf("age: %d\n", temp->age); SeqList_Destory(list); system("pause"); 80 return 0; 81 运行结果如图 2-7 所示 图 2-7 例 2-1 运行结果由图 2-7 可知, 例 2-1 中创建了一个容量为 10 的顺序表, 并且存入了 5 个元素 在本例中, 第 行代码定义了一个 Teacher 结构体, 保存了 Teacher 的姓名和年龄 ; 第 行代码创建了 5 个结点, 并且为结点中的 age 赋值 ; 第 38 行代码调用 SeqList_Create() 函数创建了一个顺序表, 第 行代码将 Teacher 的 5 个结点插入到顺序表中, 每次都从头部插入 ; 第 行代码分别调用相应函数求算顺序表的容量和长度 ; 第 行代码遍历顺序表中的元素并打印 ; 第 行代码是逐一删除顺序表中的元素, 并打印删除的元素 ; 第 77 行代码将顺序表销毁 通过本节的学习, 读者应对线性表的顺序存储有了一定的掌握 其实它并不难, 只要理清思路, 代码便是手到擒来 2.3 线性表的链式存储 ( 链表 ) 顺序表必须占用一整块事先分配好的 大小固定的存储空间, 不便于存储空间的管理, 为此有人提出可以实现存储空间的动态管理, 即链式存储方式 链表 本节就来学习什么 是链表, 以及链表的实现 链式存储的原理 在链式存储中, 结点之间的存储单元地址可能是不连续的 链式存储中每个结点都包含 两个部分 : 存储元素本身的数据域和存储结点地址的指针域 在第一章中介绍链式存储时,

12 讲解了一些链式存储的原理, 结点中的指针指向的是下一个结点, 如果结点中只有指向后继 结点的指针, 那么这些结点组成的链表称为单向链表 如图 2-8 所示, 就是一个单链表 图 2-8 单向链表一般在链表中也会有一个头结点来保存链表的信息, 然后有一个指针指向下一个结点, 下一个结点又指向它后面的一个结点, 这样直到最后一个结点, 它没有后继结点, 就指向 NULL 在链表中, 这些存储单元可以是不连续的, 因此它可以提高空间利用率, 当需要存储元素时, 哪里有空闲的空间就在哪里分配, 只要将分配的空间地址保存到上一个结点就可以, 这样通过访问前一个元素就能找到后一个元素 当在链表中某一个位置插入元素时, 从空闲空间中为该元素分配一个存储单元, 然后将两个结点之间的指针断开, 上一个结点的指针指向新分配的存储单元, 新分配的结点中指针指向下一个结点 ; 这样不需要移动原来元素的位置, 效率比较高 ; 同样, 当删除链表中的某个元素时, 就断开它与前后两个结点的指针, 然后将它的前后两个结点连接起来, 也不需要移动原来元素的位置 与顺序表相比较, 在插入删除元素方面, 链表的效率要比顺序表高许多 但是随机查找元素时, 链表没有索引标注, 存储单元的空间并不连续, 如果要查找某一个元素, 必须先得经过它的上一个结点中的地址才能找到它, 因此不管遍历哪一个元素, 都必须把它前面的元素都遍历后才能找到它, 效率就不如顺序表高 链式存储的实现 链表的几种操作与顺序表差不多, 也是增删改查几种操作 接下来我们来实现一个链表 1 创建链表以图 2-8 为例, 在创建链表时, 头结点中保存链表的信息, 则需要创建一个 struct, 在其中定义链表的信息与指向下一个结点的指针 代码如下 : struct Header // 头结点 int length; // 记录链表大小 struct Node* next; // 指向第一个结点的指针 ; 存储元素的结点包含两部分内容 : 数据域和指针域, 则也需要定义一个 struct, 代码如下 : struct Node // 结点 int data; // 数据域 struct Node* next; // 指向下一个结点的指针

13 ; 这样头结点与数据结点均已定义 为了使用方便, 将两个 struct 用 typedef 重新定义新的名称, 代码如下 : typedef struct Node List; // 将 struct Node 重命名为 List typedef struct Header phead; // 将 struct Header 重命名为 phead 创建链表要比创建顺序表简单一些 顺序表中需要先为头结点分配空间, 其次为数组分配一段连续空间, 将这段连续空间地址保存在头结点中, 然后往其中存储元素 但创建链表时, 只需要创建一个头结点, 每存储一个元素就分配一个存储单元, 然后将存储单元的地址保存在上一个结点中即可, 不需要在创建时把所有的空间都分配好 创建链表的代码如下 : phead * createlist()//phead 是 struct Header 的别名, 是头结点类型 phead* ph = (phead*)malloc(sizeof(phead)); // 为头结点分配内存 ph->length = 0; // 为头结点初始化 ph->next = NULL; return ph; // 将头结点地址返回 2 获取链表大小链表的大小等信息也是保存在头结点中, 因此需要时从头结点中获取即可, 代码如下 : int Size(pHead* ph) // 获取链表大小 if (ph == NULL) printf(" 参数传入有误!"); return 0; return ph->length; 3 插入元素在链表中插入元素时要比在顺序表中快 以图 2-8 为例, 如果要在 46 和 100 之间插入元素 99, 其插入过程也较简单 : 首先将 46 和 100 之间的连接断开, 然后 46 结点的指针指向 99, 将 99 结点的指针指向 100, 这样就完成了插入 其过程如图 2-9 所示

14 图 2-9 在链表中插入新元素在插入元素时, 不必像顺序表中那样移动元素, 效率要高很多 其代码实现如下 : // 在某一个位置插入某一个元素, 插入成功返回 1 int Insert(pHead* ph, int pos, int val) // 先作健壮性判断 if (ph == NULL pos < 0 pos > ph->length) printf(" 参数传入有误!"); return 0; // 在向链表中插入元素时, 先要找到这个位置 List* pval = (List*)malloc(sizeof(List)); // 分配内存存储要插入的数据 pval->data = val; List *pcur = ph->next; if (pos == 0) ph->next = pval; // 指针断开连接过程 pval->next = pcur; else for (int i = 1; i < pos; i++) pcur = pcur->next; // 当前指针指向头结点后的第一个结点 // 插入在第一个位置 // 找到要插入的位置 pval->next = pcur->next; pcur->next = pval; // 指针断开再连接过程 ph->length++; // 增加一个元素, 长度要加 1 return 1;

15 4 查找某个元素查找链表中的某个元素, 其效率没有顺序表高, 因为不管查找的元素在哪个位置, 都需要将它前面的元素都全部遍历才能找到它 查找的代码实现如下 : List* find(phead* ph, int val) // 查找某个元素 // 先作健壮性判断 if (ph == NULL) printf(" 参数传入有误!"); return NULL; // 遍历链表来查找元素 List *ptmp = ph->next; do if (ptmp->data == val) return ptmp; ptmp = ptmp->next; while (ptmp->next!= NULL); // 循环条件是直到链表结尾 printf(" 没有值为 %d 的元素!", val); return NULL; 5 删除元素在删除元素时, 首先将被删除元素与上下结点之间的连接断开, 然后将这两个上下结点重新连接, 这样元素就从链表中成功删除了 例如, 将图 2-9(b) 中的元素 28 删除, 其过程如图 2-10 所示

16 图 2-10 从链表中删除元素从链表中删除元素, 也不需要移动其他元素, 效率也较高 其代码实现如下 : List* Delete(pHead* ph, int val) // 删除值为 val 的元素, 删除成功, 返回删除的元素 // 先作健壮性判断 if (ph == NULL) printf(" 链表传入错误!"); return NULL; // 找到 val 值所在结点 List* pval = find(ph, val); if (pval == NULL) printf(" 没有值为 %d 的元素!", val); return NULL; // 遍历链表去找到要删除结点, 并找出其前驱及后继结点 List *pre = ph->next; // 当前结点 List *pcur = NULL; if (pre->data == val) // 如果删除的是第一个结点 ph->next = pre->next; ph->length--; return pre; else // 如果删除的是其他结点 for (int i = 0; i < ph->length; i++) // 遍历链表 pcur = pre->next;

17 if (pcur->data == val) // 找到要删除的元素 pre->next = pcur->next; // 将被删除元素的上下两个结点连接起来 ph->length--; // 长度减 1 return pcur; // 将被删除的元素结点返回 pre = pre->next; 6 销毁链表销毁链表时, 将链表中每个元素结点释放掉, 可以将头结点释放掉 ; 但也可以保留头结点, 将其置于初始化状态 代码实现如下 : void Destory(pHead* ph) // 销毁链表 List *pcur = ph->next; List *ptmp; if (ph == NULL) printf(" 参数传入有误!"); while (pcur->next!= NULL) ptmp = pcur->next; free(pcur); // 将结点释放 pcur = ptmp; ph->length = 0; // 回到初始化状态 ph->next = NULL; 在本例中, 没有释放掉头结点, 只是将头结点中的信息归于了初始化状态 7 遍历打印链表实现出链表的遍历打印函数, 是为了在接下来的测试程序中避免代码重复, 打印链表的代码如下 : void print(phead *ph) if (ph == NULL) printf(" 参数传入有误!"); List *ptmp = ph->next; while (ptmp!= NULL) printf("%d ", ptmp->data);

18 ptmp = ptmp->next; printf("\n"); 至此, 链表基本的操作都已经实现, 接下来可以用测试程序来测试这个链表的使用情况 同样, 由于上述操作函数都已经实现, 在接下来的测试中只给出头文件 list.h 和测试代码文件 main.c, 而函数实现 list.c, 读者可以复制上述各操作函数的代码, 也可以试着自己来实现 具体如例 2-2 所示 例 2-2 list.h // 头文件 1 #ifndef _LIST_H_ 2 #define _LIST_H_ 3 4 struct Node; 5 typedef struct Node List; 6 typedef struct Header phead; 7 8 phead * createlist(); // 创建链表 9 int isempty(phead* l); // 判断链表是否为空 10 int Insert(pHead* l, int pos, int val); // 插入元素, 插入成功返回 1; 11 List* Delete(pHead* l, int ele); // 删除元素, 删除成功, 返回删除的元素 12 List* find(phead* l, int ele); // 查找某个元素是否存在 13 int Size(pHead* l); // 获取链表大小 14 void Destory(pHead* l); // 销毁链表 15 void print(phead *l); // 打印链表 struct Node // 结点 int data; // 数据域 20 struct Node* next; // 指向下一个结点的指针 21 ; struct Header // 头结点 int length; // 记录链表大小 26 struct Node* next; 27 ; 28 #endif main.c // 测试文件 29 #define _CRT_SECURE_NO_WARNINGS 30 #include "list.h" 31 #include <stdio.h> 32 #include <stdlib.h> 33

19 34 int main() int ret; 37 phead *ph = createlist(); // 创建链表 38 if (ph == NULL) printf(" 创建链表失败!\n"); int arr[10] = 1, 2, 3, 4, 56, 76, 7, 4, 36, 34;// 定义一个 int 类型数组 for (int i = 0; i <= 6; i++) Insert(ph, 0, arr[i]); // 将数组元素插入到链表中, 每次都从头部插入 printf(" 链表长度 :%d\n", Size(ph)); printf(" 打印链表中的元素 :\n"); 52 print(ph); 53 printf(" 删除链表中的元素, 请输入要删除的元素 :\n"); 54 int num; 55 scanf("%d", &num); // 本例中为测试程序, 为减少异常处理, 请输入链表中有的元素 56 Delete(ph, num); 57 printf(" 元素删除成功, 删除元素 %d 后, 链表中元素为 :\n", num); 58 print(ph); ret = find(ph, 3); // 查找链表中某一个元素 61 if (ret) 62 printf("get!\n"); 63 else 64 printf("no!\n"); system("pause"); 67 return 0; 68 运行如图 2-11 所示 图 2-11 例 2-2 运行结果

20 在例 2-2 中, 第 37 行代码创建了一个链表 ; 第 行定义了一个 int 类型数组, 并将数组中的元素插入到了链表中 ; 第 49 行代码打印出了链表的长度, 由图 2-11 可知, 链表长度为 7; 第 52 行代码调用 print() 函数遍历打印出了链表中的元素 ; 第 行代码是删除链表中的某个元素, 从键盘输入的元素为 4, 即删除链表中的元素 4; 第 58 行代码又调用 print() 函数重新打印删除 4 后的链表元素, 由图 2-11 的运行结果可知, 元素 4 删除成功 ; 第 行代码是查找链表中是否有值为 3 的元素, 由运行结果可知, 这个元素存在 至此, 线性表的顺序存储与链式存储, 包括其原理和实现方式都已讲解完毕, 相信读者对这两种表也有了一定的掌握, 其实只要理解了其存储原理, 思路清晰, 代码实现并不难 掌握了这两种最基本的线性表, 对接下来其他数据结构的学习会有很大帮助 2.4 双向链表 上一节学习了单链表, 但是单链表有一个缺点, 无法快速访问前驱结点, 当查找到某一个元素时, 如果想找前面的元素结点, 需要再次从头遍历, 这样就比较麻烦 那么就有人提出了, 是否可以在结点中再增加一个指针来指向前驱结点? 答案是可以的 增加了指向前驱结点的指针的链表称为双向链表, 本节就来学习一下 什么是双向链表 双向链表, 顾名思义就是可以向两个方向走的链表 它的每一个结点有两个指针, 一个 指向后继结点, 一个指向前驱结点 如图 2-12 所示 图 2-12 双向链表图 2-12 中的双向链表, 第一个结点的前驱指针 pre 指向了 NULL, 当然, 读者在设计时也可以将它指向头结点 ; 最后一个结点的后继结点 next 指向了 NULL, 这和单链表是一样的 在双向链表中, 通过一个结点可以找到它的后继结点, 也可以找到它的前驱结点 双向链表在结构和算法描述上和单链表相同, 只是某些算法实现比单链表复杂一些 例如, 在插入元素时, 需要同时修改两个方向的指针指向 以图 2-12 中的双向链表为例, 在元素 12 与 99 之间插入新元素 33, 其过程如图 2-13 所示

21 图 2-13 在双链表中插入元素从图 2-13 演示的过程中, 可以看出, 在插入元素时, 需要同时修改两个方向的指针指向 同理, 在删除元素时, 也要修改两个指针, 这里我们就不再做相应的图解演示 前面已学习过单链表的实现过程, 双向链表的实现与单链表的实现大同小异, 因此在本节学习完双链表之后, 读者可以试着自己来实现一下双链表的基本操作, 然后再对比与本书中双向链表的实现有何异同 双向链表的实现 学习完双链表的定义与基础操作之后, 我们用 C 语言来实现一个双链表 此双向链表所具有的功能如下所示 : l 创建双向链表 l 获取双向链表的长度 l 判断双向链表是否为空 l 插入 删除 查找元素 l 销毁双向链表 l 打印双向链表

22 在学习单链表时, 每一种操作算法都有详细的描述与实现代码, 双向链表与单链表有很 多操作是相似的, 不再详细描述, 只给出案例代码 具体如例 2-3 所示 例 2-3 dlist.h // 头文件 1 #ifndef _DLIST_H_ 2 #define _DLIST_H_ 3 4 struct Node; 5 typedef struct Head* phead; // 头结点类型 6 typedef struct Node* pnode; // 数据结点类型 7 // 定义头结点 8 struct Head 9 10 int length; 11 pnode next; // 指向下一个结点的指针 12 ; 13 // 定义数据结点 14 struct Node int data; 17 pnode pre; // 指向前驱结点的指针 18 pnode next; // 指向后继结点的指针 19 ; phead DlistCreate(); // 创建双向链表 22 int getlength(phead ph); // 获取双向链表的长度 23 int IsEmpty(pHead ph); // 判断链表是否为空 24 int DlistInsert(pHead ph, int pos, int val); // 在链表的 pos 位置插入元素 val 25 pnode DlistDelete(pHead ph, int val); // 删除双向链表 ph 中的元素 val 26 pnode DlistFind(pHead ph, int val); // 查找双向链表中是否有值为 val 的元素 27 void DlistDestory(pHead ph); // 销毁链表 28 void printfront(phead ph); // 打印双向链表中的元素 29 void printlast(phead ph); 30 #endif dlist.c // 函数实现文件 31 #include "dlist.h" 32 #include <stdio.h> 33 #include <stdlib.h> phead DlistCreate() // 创建双向链表 phead ph = (phead)malloc(sizeof(struct Head)); // 为头结点分配空间 38 if (ph == NULL) 39 printf(" 分配头结点失败!"); // 为了方便运行结果查看, 不设置 return 返回

23 40 // 创建好头结点后, 初始化头结点中数据 41 ph->length = 0; 42 ph->next = NULL; 43 return ph; // 将头结点返回 int getlength(phead ph) // 获取双向链表的长度 // 先对传入进来的链表作健壮性检查 48 if (ph == NULL) 49 printf(" 传入的双链表有误!"); 50 return ph->length; int IsEmpty(pHead ph) // 判断双链表是否为空 if (ph == NULL) 56 printf(" 传入的双链表有误!"); 57 if (ph->length == 0) // 如果长度为 0, 则链表为空 58 return 1; 59 else 60 return 0; int DlistInsert(pHead ph, int pos, int val) // 在链表的 pos 位置插入元素 val pnode pval = NULL; 66 // 先作健壮性判断 67 if (ph == NULL pos < 0 pos > ph->length) 68 printf(" 插入元素时, 参数传入有误!"); // 如果参数无误, 就要为元素分配结点空间 71 pval = (pnode)malloc(sizeof(struct Node)); 72 pval->data = val; // 将值 val 保存到此结点中 // 接下来要判断在哪个位置插入元素, 先判断链表是否为空 75 if (IsEmpty(ph)) // 如果链表为空 ph->next = pval; // 直接将结点插入到头结点后 78 pval->next = NULL; 79 pval->pre = NULL; // 第一个结点不回指头结点 else // 如果双链表不为空, 则要判断是插入哪个位置 pnode pcur = ph->next;

24 84 if (pos == 0) // 在第一个位置 ( 头结点后 ) 插入 ph->next = pval; // 头结点指向 pval 87 pval->pre = NULL; 88 pval->next = pcur; //pval 的后继指针指向 pcur 89 pcur->pre = pval; //pcur 前驱指针指向 pval else // 如果不是插入到第一个位置 for (int i = 1; i < pos; i++) // 就要遍历链表找到要插入的位置 pcur = pcur->next; //pcur 指针向后移 // 循环结束后, 此时 pcur 指向的是要插入的位置 98 pval->next = pcur->next; // 指针断开再连接的过程 99 pcur->next->pre = pval; 100 pval->pre = pcur; 101 pcur->next = pval; ph->length++; 105 return 1; pnode DlistDelete(pHead ph, int val) // 删除双向链表 ph 中的元素 val if (ph == NULL ph->length == 0) printf(" 参数传入有误!"); // 如果参数无误, 则遍历找到值为 val 的元素, 然后将其删除 115 pnode pval = DlistFind(ph, val); // 找到值所在的结点 116 if (pval == NULL) return NULL; printf(" 将其删除 \n"); 121 // 因为双链表中的结点既有前驱结点又有后继结点 122 pnode pre = pval->pre; //pre 指向 pval 结点的前驱结点 123 pnode pnext = pval->next; //pnext 指向 pval 结点的后继结点 pre->next = pnext; 126 pnext->pre = pre; 127 return pval;

25 pnode DlistFind(pHead ph, int val) // 查找某个元素 if (ph == NULL) printf(" 参数传入有误!"); // 如果参数无误, 则需要遍历双链表, 查找要找的元素 137 pnode ptmp = ph->next; // 此过程与单链表无异 138 do if (ptmp->data == val) printf(" 有此元素!\n"); 143 return ptmp; ptmp = ptmp->next; 146 while (ptmp->next!= NULL); // 循环条件是直到链表结尾 printf(" 没有值为 %d 的元素!\n", val); 149 return NULL; void DlistDestory(pHead ph) // 销毁链表 pnode pcur = ph->next; 155 pnode ptmp; 156 if (ph == NULL) 157 printf(" 参数传入有误!"); while (pcur->next!= NULL) ptmp = pcur->next; 162 free(pcur); // 将结点释放 163 pcur = ptmp; ph->length = 0; // 回到初始化状态 166 ph->next = NULL; void printfront(phead ph) // 打印双向链表中的元素, 从前往后打印 if (ph == NULL)

26 printf(" 参数传入有误!"); pnode ptmp = ph->next; 176 while (ptmp!= NULL) printf("%d ", ptmp->data); 179 ptmp = ptmp->next; printf("\n"); void printlast(phead ph) // 倒序打印, 从链表末尾开始向前打印 if (ph == NULL) printf(" 参数传入有误!"); pnode ptmp = ph->next; 191 while (ptmp->next!= NULL) ptmp = ptmp->next; // 先将指针 ptmp 移动到末尾结点 for (int i = --ph->length; i >= 0; i--) // 从末尾结点向前打印元素 printf("%d ", ptmp->data); 198 ptmp = ptmp->pre; printf("\n"); 201 main.c // 测试文件 202 #define _CRT_SECURE_NO_WARNINGS 203 #include "dlist.h" 204 #include <stdio.h> 205 #include <stdlib.h> 206 int main() // 创建一个双向链表 209 phead ph = NULL; 210 ph = DlistCreate(); // 向链表中插入元素 213 int num; 214 printf(" 请输入要插入的元素, 输入 0 结束 :\n");

27 215 while (1) scanf("%d", &num); 218 if (num == 0) 219 break; 220 DlistInsert(ph, 0, num); // 本测试程序从头部插入 printf(" 双链表长度 :%d\n", getlength(ph)); 224 printfront(ph); // 从前往后打印双链表的元素 225 DlistInsert(ph, 3, 99); // 在 3 位置插入新元素 printfront(ph); // 然后再从前往后打印双链表的元素 227 printlast(ph); // 从后往前打印元素 int val; 230 printf(" 请输入要查找的元素 :\n"); 231 scanf("%d", &val); 232 DlistFind(ph, val); // 查找元素 int del; 235 printf(" 请输入要删除的元素 :\n"); 236 scanf("%d", &del); 237 DlistDelete(ph, del); // 删除元素 238 printfront(ph); // 打印删除元素后的链表 DlistDestory(ph); // 销毁链表 241 printf(" 双链表销毁成功!\n 此时链表长度为 :%d\n", ph->length); system("pause"); 244 return 0; 245 运行结果如图 2-14 所示 图 2-14 例 2-3 运行结果

28 在例 2-3 双链表的实现中, 只实现了双链表的增删改查几个基本功能 双向链表的插入删除操作, 实现起来比单链表的稍微复杂一些, 其他操作都无大的改动 双链表是可以倒序遍历的, 为了测试该双链表的功能, 我们在最后的打印链表元素时, 增加了一个倒序打印函数 printlast(), 从后往前打印链表的元素 相对于单链表来说, 双向链表要复杂一些, 因为它多了一个前驱指针, 所以对于插入和删除操作的实现要格外小心 另外, 因为双链表中的每个结点要记录两个指针, 所以空间消耗要略多一些 不过由于它良好的对称性, 使得对某个结点的前后两个结点操作更灵活, 也使算法的时间效率得到了提高, 说到底, 就是用空间换时间 2.5 循环链表 链表中还有一种常用的形式, 那就是循环链表, 看到循环二字, 想必读者已经知道它是 一种怎样的链表了, 不错, 这种链表头尾相接, 形成了一个环 那么它又具有什么样的特性 呢, 本节就来探讨一下 什么是循环链表 循环链表是首尾相接的一种链表, 它尾结点的后继指针又指向链表的第一个结点, 这样 形成了一个环 对于循环链表, 从表中的任何一个结点出发, 能找到其它所有的结点 如图 2-15 所示, 是一种单向的循环链表 图 2-15 单循环链表 循环链表的形式有好几种, 如双循环链表 多重循环链表 ( 将表中结点链在多个环上 ) 等 多重循环链表示例如图 2-16 所示 图 2-16 多重循环链表图 2-16 就是一个多重循环链表, 元素 26 所在的结点既在左边的循环链中, 又在右边的循环链中 多重循环链表并不常用, 我们在讲循环链表时, 主要讲解的是单链的循环链表 循环链表, 既有单链表的优点又有双向链表的优点, 相对于单链表, 双向链表需要为每个结点增加部分存储空间保存前驱指针的信息, 而循环链表无须增加储存量, 只是改变了尾

29 结点中后继指针的指向, 就使操作更加灵活多变 需要注意的是, 循环链表中没有 NULL 指针, 涉及遍历操作时, 其终止条件就不再是非循环链表中判别 pnode->next 是否为空, 而是判别它们是否等于某一指定指针, 如头指针或尾指针等, 用代码表示, 如下所示 : if(pnode->next == phead->next) 循环链表的实现 在单链表中, 从一已知结点出发, 只能访问到该结点及其后继结点, 无法找到该结点之前的其它结点 而在单循环链表中, 从任一结点出发都可访问到表中所有结点, 这一优点使某些运算在单循环链表上更易于实现 循环链表在实现上大多操作都与单链表相同, 如创建 查找等, 这些部分在单链表与双向链表中都有详细的讲解及代码实现, 此处就不再重复, 接下来主要讲解其插入与删除元素时与单链表的异同 1 插入元素在循环链表中插入元素, 如果是插入到第一个位置, 即头结点之后的位置, 则稍稍有一些麻烦, 需要处理三个指针, 头结点中的指针 尾结点中的指针和插入元素的结点指针 其过程如图 2-17 所示 图 2-17 在循环链表的头结点插入元素在头结点之后插入元素时, 要将新结点中的指针指向此位置上原来的结点, 头结点中的指针指向新结点, 尾结点指针指向新结点 比单链表多处理了一个尾结点指针 在尾部插入元素时也有所不同,p->next 不再指向 NULL, 而是指向 head->next 除此两处以外, 在其他位置插入元素, 则与单链表处理相同 其代码实现如下 : int ClistInsert(pHead ph, int pos, int val) // 在链表的 pos 位置插入元素 val

30 if (ph == NULL pos < 0 pos > ph->length) printf(" 插入元素时, 参数传入有误!\n"); pnode pval = NULL; // 参数传入无误, 则为新元素 val 分配结点 pval = (pnode)malloc(sizeof(struct Node)); pval->data = val; // 将值 val 保存到此结点中 // 接下来要判断在哪个位置插入元素, 先判断链表是否为空 if (IsEmpty(ph)) // 如果链表为空 ph->next = pval; // 直接将结点插入到头结点后 pval->next =pval; // 将第一个结点指向它自己 else // 循环链表不为空, 则分为在头部插入 ( 即头结点后 ) 和普通位置插入 pnode prear = ph->next; if (pos == 0) // 在第一个位置 ( 头结点后 ) 插入 // 在 0 号位置插入, 需要先找到尾结点 while (prear->next!= ph->next) // 循环结束的条件 prear = prear->next; //pcur 指针向后移动 //while 循环结束后,pRear 指向尾结点 // 然后插入元素 pval->next = ph->next; ph->next = pval; prear->next = pval; // 这三个步骤顺序不能更改 else // 如果不是 0 号位置插入, 则和单链表无区别 pnode pcur = ph->next; for (int i = 1; i < pos; i++) // 就要遍历链表找到要插入的位置 pcur = pcur->next; //pcur 指针向后移 // 循环结束后, 此时 pcur 指向的是要插入的位置 pval->next = pcur->next; // 指针断开再连接的过程 pcur->next = pval;

31 ph->length++; return 1; 在插入新元素时, 先判断链表是否为空, 如果为空, 则将元素插入到头结点后, 然后将其指针指向自身 ; 如果不为空, 根据插入的位置作出相应操作 2 删除元素在删除元素时, 也要考虑删除的是否为头结点后的第一个元素, 如果是, 则需要将头结点与尾结点的指针指向待删除结点的后继结点, 如图 2-18 所示 图 2-18 删除头结点后的第一个元素如果是删除其他位置的元素, 则和单链表处理方式相同 其代码实现如下 : pnode ClistDelete(pHead ph, int val) // 删除循环链表 ph 中的元素 val if (ph == NULL ph->length == 0) printf(" 参数传入有误!"); // 先找到链表的尾结点 pnode prear = ph->next; while (prear->next!= ph->next) prear = prear->next; // 查找此元素 pnode pval = ClistFind(ph, val); if (pval == NULL) return NULL; // 关于 ClistFind() 函数, 与单链表相同 if (pval == ph->next) // 如果是第 0 号位置上的结点

32 ph->next = pval->next; prear->next = pval->next; else // 如果是其他位置的结点 // 就要找到 pval 的前驱结点 pnode pre = ph->next; for (int i = 0; i < ph->length; i++) if (pre->next == pval) pre->next = pval->next; return pval; pre = pre->next; return NULL; 在循环链表中, 除了插入和删除操作与单链表稍有不同之外, 其他操作与单链表都是一样的, 读者可以参照单链表的操作自己动手实现循环链表, 并完成测试 约瑟夫环 约瑟夫问题是循环链表的一个典型应用, 其描述如下 :m 个人围成了一圈, 从其中任一个人开始, 按顺时针顺序使所有人依次从 1 开始报数, 报到 n 的人出列 ; 然后使 n 之后的人接着从 1 开始报数, 再次使报到 n 的人出列 如此下去, 求算出列的顺序, 及最后留下来的人的编号 为了更清晰的描述问题, 可以将 m 与 n 设定为具体数字, 如 m = 8,n = 3, 即 8 个人围坐成一圈 为这 8 个人编号, 使编号为 1 的人从 1 开始报数, 报到 3 的人出局 ; 编号为 4 的人再从 1 开始报数, 报到 3 的出局 如此重复, 直到这 8 个人全部出局 出局过程如图 2-19 所示

33 图 2-19 约瑟夫环 第一轮 : 从 1 到 3, 第 3 个人出局 第二轮 : 第 4 个人从 1 开始报数, 第 6 个人报到 3, 则第 6 个人出局 第三轮 : 第 7 个人从 1 开始报数, 第 1 个人报到 3, 则第 1 个人出局 第四轮 : 第 2 个人从 1 开始报数, 第 5 个人报到 3, 则第 5 个人出局 第五轮 : 第 7 个人从 1 开始报数, 第 2 个人报到 3, 则第 2 个人出局 第六轮 : 第 4 个人从 1 开始报数, 第 8 个人报到 3, 则第 8 个人出局 第七轮 : 第 4 个人从 1 开始报数, 此时只剩下他和 7, 他自己报到 3, 则第 4 个人出局 最后这一圈人只剩下 7 当数据量较小时, 通过作图我们很轻易地就能找出出列顺序, 但当数据量较大时, 人工 计算几乎是不可能的 要解决这样的问题, 需要借助一定的编程算法, 而我们刚刚学习过的 循环链表就正好可以用来解决此问题 首先用这些数据创建一个循环链表 ; 然后设置限制条 件并循环遍历链表, 当遍历到要出局的元素时, 就将其删除, 这样循环操作直到链表中只剩 下一个结点 具体代码实现如例 2-4 所示 例 2-4 clist.h // 头文件 1 #ifndef _CLIST_H_ 2 #define _CLIST_H_ 3 4 struct Node; 5 typedef struct Head* phead; // 头结点类型 6 typedef struct Node* pnode; // 数据结点类型 7 // 定义头结点 8 struct Head 9 10 int length; 11 pnode next; // 指向下一个结点的指针 12 ;

34 13 // 定义数据结点 14 struct Node int data; 17 pnode next; // 指向后继结点的指针 18 ; 19 phead ClistCreate(); // 创建循环链表 20 int getlength(phead ph); // 获取循环链表的长度 21 int IsEmpty(pHead ph); // 判断链表是否为空 22 int ClistInsert(pHead ph, int pos, int val); // 在链表的 pos 位置插入元素 val 23 void print(phead ph); // 打印循环链表中的元素 #endif clist.c // 文件 26 #include "clist.h" 27 #include <stdio.h> 28 #include <stdlib.h> phead ClistCreate() // 创建循环链表 phead ph = (phead)malloc(sizeof(struct Head)); // 为头结点分配空间 33 if (ph == NULL) 34 printf(" 分配头结点失败!"); // 为了方便运行结果查看, 不设置 return 返回 35 // 创建好头结点后, 初始化头结点中数据 36 ph->length = 0; 37 ph->next = NULL; 38 return ph; // 将头结点返回 int IsEmpty(pHead ph) // 判断链表是否为空 if (ph == NULL) 44 printf(" 传入的循环链表有误!"); 45 if (ph->length == 0) // 如果长度为 0, 则链表为空 46 return 1; 47 else 48 return 0; int ClistInsert(pHead ph, int pos, int val) // 在链表的 pos 位置插入元素 val if (ph == NULL pos < 0 pos > ph->length) 55

35 56 printf(" 插入元素时, 参数传入有误!\n"); pnode pval = NULL; 60 // 参数传入无误, 则为新元素 val 分配结点 61 pval = (pnode)malloc(sizeof(struct Node)); 62 pval->data = val; // 将值 val 保存到此结点中 // 接下来要判断在哪个位置插入元素, 先判断链表是否为空 65 if (IsEmpty(ph)) // 如果链表为空 ph->next = pval; // 直接将结点插入到头结点后 68 pval->next = pval; // 将第一个结点指向它自己 else // 循环链表不为空, 则分为在头部插入 ( 即头结点后 ) 和普通位置插入 pnode prear = ph->next; 73 if (pos == 0) // 在第一个位置 ( 头结点后 ) 插入 // 在 0 号位置插入, 需要先找到尾结点 76 while (prear->next!= ph->next) // 循环结束的条件 prear = prear->next; //pcur 指针向后移动 //while 循环结束后,pRear 指向尾结点 81 // 然后插入元素 82 pval->next = ph->next; 83 ph->next = pval; 84 prear->next = pval; // 这三个步骤顺序不能更改 else // 如果不是 0 号位置插入, 则和单链表无区别 pnode pcur = ph->next; 89 for (int i = 1; i < pos; i++) // 就要遍历链表找到要插入的位置 pcur = pcur->next; //pcur 指针向后移 // 循环结束后, 此时 pcur 指向的是要插入的位置 94 pval->next = pcur->next; // 指针断开再连接的过程 95 pcur->next = pval; ph->length++; 99 return 1;

36 void print(phead ph) // 打印循环链表中的元素 if (ph == NULL ph->length == 0) printf(" 参数传入有误!"); pnode ptmp = ph->next; for (int i = 0; i < ph->length ; i++) printf("%d ", ptmp->data); 114 ptmp = ptmp->next; printf("\n"); 117 Joseph.c // 测试文件 118 #define _CRT_SECURE_NO_WARNINGS 119 #include "clist.h" 120 #include <stdio.h> 121 #include <stdlib.h> int main() int m, n; 126 printf(" 请输入约瑟夫环的总人数 :\n"); 127 scanf("%d", &m); 128 if (m <= 0) printf(" 请输入正确的数字!\n"); 131 return 0; printf(" 请输入出局者的报数 :\n"); 134 scanf("%d", &n); 135 if (n <= 0) printf(" 请输入正确的数字!\n"); 138 return 0; // 根据输入的 m 创建链表 142 phead ph = NULL;

37 143 ph = ClistCreate(); 144 if (ph == NULL) printf(" 创建循环链表失败!\n"); 147 return 0; // 插入元素 151 for (int i = m; i > 0; i--) ClistInsert(ph, 0, i); // 使用头插法从 m 到 1 倒序插入 print(ph); 157 printf(" 出局顺序 :\n"); 158 // 插入元素后, 就循环遍历链表 159 pnode node = ph->next; //node 指针指向第一个结点 160 while (node->next!= node) // 循环结束条件, 结点指向其自身, 此时剩最后一个结点 for (int i = 1; i < n - 1; i++) //i < n - 1, 报到 n 就重新开始 node = node->next; //for 循环结束后,node 指针指向待出局的结点的前驱结点 167 pnode ptmp = node->next; //ptmp 指向要被踢出的结点 // 接下来先要判断这个结点是 0 号位置的结点还是其他位置的结点 170 if (ptmp == ph->next) // 如果此结点在 0 号位置 ph->next = ptmp->next; // 头结点也要作处理 173 node->next = ptmp->next; 174 printf("%d ", ptmp->data); 175 free(ptmp); 176 ph->length--; else // 如果此结点在其他位置 node->next = ptmp->next; 181 printf("%d ", ptmp->data); 182 free(ptmp); 183 ph->length--; node = node->next; 186

38 187 node->next = node; 188 printf("\n"); //循环结束 只剩下 node 一个结点 让其指向自身 printf("链表中最后留下的是 "); 191 print(ph); system("pause"); 194 return 0; 195 运行结果如图 2-20 所示 图2-20 例 2-4 运行结果 在例 2-4 中 创建一个循环链表 以循环链表为基础来计算这一圈人的出局序列 并求 出最后留下来的人 解决约瑟夫问题并没有用到循环链表的全部算法 因此在本例中只实现 了此问题涉及的操作 首先创建一个循环链表 使用每位参与者信息初始化该链表 然后开 始遍历 第 159~187 行代码是将报数为 n 的结点删除 第 160 行代码的循环条件是 node->next!= node 即当链表中只剩一个结点时终止循环 while 循环里用一个 for 循环 第 行代码 来控制报数情况 报到 n 就将此结点删除 2.6 本章小结 本章作为进入数据结构部分的第一章 讲解了最简单的数据结构 线性表 具体包括 常用的顺序表 单链表 双向链表 循环链表 本章针对每一种表分析了它们的逻辑关系 存储原理 并给出了它们常用操作的详细代码实现 通过本章的学习 读者可以掌握线性表 的原理及实现 并使用线性表来解决一些简单的问题 为以后学习其他数据结构打下坚实的 基础 思考题 请从存储结构 基本操作两方面简述顺序表与链表的不同 之处 扫描右 维码 查看思考题答案 北京市昌平区建材城西路金燕龙办公楼一层 电话

Microsoft Word - 专升本练习2:线性表.doc

Microsoft Word - 专升本练习2:线性表.doc 第二章 线性表 一 选择题 1. 线性表是 ( ) A. 一个有限序列, 可以为空 B. 一个有限序列, 不能为空 C. 一个有限序列, 可以为空 D. 一个无序序列, 不能为空 2. 对顺序存储的线性表, 设其长度为 n, 在任何位置上插入或删除操作都是等概率 插入一个元素 时大约要移动表中的 ( ) 个元素, 删除一个元素时大约要移动表中的 ( ) 个元素 A. n/2 B. (n+1)/2 C.

More information

2.3 链表

2.3  链表 数据结构与算法 ( 二 ) 张铭主讲 采用教材 : 张铭, 王腾蛟, 赵海燕编写高等教育出版社,2008. 6 ( 十一五 国家级规划教材 ) https://pkumooc.coursera.org/bdsalgo-001/ 第二章线性表 2.1 线性表 2.2 顺序表 tail head a 0 a 1 a n-1 2.4 顺序表和链表的比较 2 链表 (linked list) 通过指针把它的一串存储结点链接成一个链

More information

Microsoft Word - 数据结构实训与习题725xdy.doc

Microsoft Word - 数据结构实训与习题725xdy.doc 第一部分学习指导与实训 3 第 2 章线性表 2.1 学习指南 (1) 理解线性表的类型定义, 掌握顺序表和链表的结构差别 (2) 熟练掌握顺序表的结构特性, 熟悉顺序表的存储结构 (3) 熟练掌握顺序表的各种运算, 并能灵活运用各种相关操作 (4) 熟练掌握链式存储结构特性, 掌握链表的各种运算 2.2 内容提要 线性表的特点 : 线性表由一组数据元素构成, 表中元素属于同一数据对象 在线性表中,

More information

2

2 孙猛 http://www.math.pku.edu.cn/teachers/sunm 2017 年 9 月 18 日 课程主 页 : http://www.math.pku.edu.cn/teachers/sunm/ds2017/ 作业通过 course.pku.edu.cn 提交 2 线性表的概念和抽象数据类型 顺序表示 链接表示 3 4 线性表 ( 简称为表 ) 是零个或多个元素的有穷序列列

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

Microsoft PowerPoint - 2线性表.ppt [兼容模式]

Microsoft PowerPoint - 2线性表.ppt [兼容模式] 2 线性表 董洪伟 http://hwdong.com 1 主要内容 线性表的类型定义 即抽象数据类型 顺序实现 即用一连续的存储空间来表示 链式实现 即用链表实现 一元稀疏多项式 链表实现 2 线性表的类型定义 线性表 n 个元素的有限序列 数据项 元素 ( 记录 ) 姓名 学号 性别 年龄 班级 健康状况 王小林 790631 男 18 计 91 健康 陈红 790632 女 20 计 91 一般

More information

Microsoft PowerPoint - ds_2.ppt

Microsoft PowerPoint - ds_2.ppt 第二章线性表 2.1 线性表的概念 2.2 顺序表示 2.3 链接表示 2.4 应用举例 -Josehus 问题另外介绍 动态顺序表 程序里常需要保存一批某种类型的元素, 这些元素的数目可能变化 ( 可以加入或删除元素 ) 有时需要把这组元素看成一个序列, 元素的顺序可能表示实际应用中的某种有意义的关系这样一组元素可以抽象为元素的一个线性表 线性表是元素的集合, 同时记录了元素的顺序关系 线性表是一种最基本的数据结构,

More information

PowerPoint Presentation

PowerPoint Presentation 数据结构与算法 ( 六 ) 张铭主讲 采用教材 : 张铭, 王腾蛟, 赵海燕编写高等教育出版社,2008. 6 ( 十一五 国家级规划教材 ) http://www.jpk.pku.edu.cn/pkujpk/course/sjjg 第 6 章树 C 树的定义和基本术语 树的链式存储结构 子结点表 表示方法 静态 左孩子 / 右兄弟 表示法 动态表示法 动态 左孩子 / 右兄弟 表示法 父指针表示法及其在并查集中的应用

More information

幻灯片 1

幻灯片 1 C Programming Language Lecture 12 Chengwei Zhang ( 张成伟 ) Tian Xia ( 夏天 ) Dept. of Electronics and Information Eng. Huazhong University of Science and Technology Feb. 2014 Lecture 12 Chapter 11: C Data

More information

C 1

C 1 C homepage: xpzhangme 2018 5 30 C 1 C min(x, y) double C // min c # include # include double min ( double x, double y); int main ( int argc, char * argv []) { double x, y; if( argc!=

More information

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式] Arrays and Strings 存储同类型的多个元素 Store multi elements of the same type 数组 (array) 存储固定数目的同类型元素 如整型数组存储的是一组整数, 字符数组存储的是一组字符 数组的大小称为数组的尺度 (dimension). 定义格式 : type arrayname[dimension]; 如声明 4 个元素的整型数组 :intarr[4];

More information

《C语言程序设计》教材习题参考答案

《C语言程序设计》教材习题参考答案 教材名称 : C 语言程序设计 ( 第 1 版 ) 黄保和 江弋编著清华大学出版社 ISBN:978-7-302-13599-9, 红色封面 答案制作时间 :2011 年 2 月 -5 月 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p=&a 2. 设已定义 int x,*p=&x;, 则下列表达式中错误的是 :B)&*x 3. 若已定义 int a=1,*b=&a;,

More information

Microsoft PowerPoint - 08 指针

Microsoft PowerPoint - 08 指针 能源与动力工程学院 目录 指针 (Pointer) 陈 斌 第二节指针数组第四节指针的应用 Fortran 90/95 引入了指针的概念 指针变量的声明方法为 : Fortran 语言中, 一个指针变量可以动态地指向某个数据对象, 或者说, 对此数据对象起了一个别名 Fortran 中的指针与 C 语言中的指针并不相同, 因为它并不代表一个变量在内部存储单元中的地址, 而是代表这个变量的别名, 实质上它相当于

More information

《C语言程序设计》第2版教材习题参考答案

《C语言程序设计》第2版教材习题参考答案 教材 C 语言程序设计 ( 第 2 版 ) 清华大学出版社, 黄保和, 江弋编著 2011 年 10 月第二版 ISBN:978-7-302-26972-4 售价 :35 元 答案版本 本习题答案为 2012 年 2 月修订版本 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p = &a A. *p = *a B. p = *a C.p = &a D. *p =

More information

Microsoft PowerPoint - DS_Ch2.ppt [兼容模式]

Microsoft PowerPoint - DS_Ch2.ppt [兼容模式] 数据结构 Ch.2 线性表 计算机学院 肖明军 Email: xiaomj@ustc.edu.cn http://staff.ustc.edu.cn/~xiaomj 2.1 线性表的逻辑结构 线性表 : 由 n(n 0) 个结点 a 1,, a n 组成的有限序列 记作 :L = (a 1, a 2,, a n ), 属性 : 长度 ---- 结点数目 n,n=0 时为空表 a i ---- 一般是同一类型

More information

PowerPoint Presentation

PowerPoint Presentation 数据结构与算法 ( 二 ) 张铭主讲 采用教材 : 张铭, 王腾蛟, 赵海燕编写高等教育出版社,2008. 6 ( 十一五 国家级规划教材 ) https://pkumooc.coursera.org/bdsalgo-001/ 第二章 线性表 第二章线性表 2.1 线性表 2.2 顺序表 2.3 链表 {a 0, a 1,, a n 1 } a 0 a 1 a 2 a n-1 tail head a

More information

C/C++ - 文件IO

C/C++ - 文件IO C/C++ IO Table of contents 1. 2. 3. 4. 1 C ASCII ASCII ASCII 2 10000 00100111 00010000 31H, 30H, 30H, 30H, 30H 1, 0, 0, 0, 0 ASCII 3 4 5 UNIX ANSI C 5 FILE FILE 6 stdio.h typedef struct { int level ;

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc 2 5 8 11 0 13 1. 13 2. 15 3. 18 1 23 1. 23 2. 26 3. 28 2 36 1. 36 2. 39 3. 42 4. 44 5. 49 6. 51 3 57 1. 57 2. 60 3. 64 4. 66 5. 70 6. 75 7. 83 8. 85 9. 88 10. 98 11. 103 12. 108 13. 112 4 115 1. 115 2.

More information

untitled

untitled 1 DBF (READDBF.C)... 1 2 (filetest.c)...2 3 (mousetes.c)...3 4 (painttes.c)...5 5 (dirtest.c)...9 6 (list.c)...9 1 dbf (readdbf.c) /* dbf */ #include int rf,k,reclen,addr,*p1; long brec,erec,i,j,recnum,*p2;

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

Microsoft Word - CSJ05.doc

Microsoft Word - CSJ05.doc 第 5 章 设备信息管理 本章设计并实现一个设备信息管理程序, 要求实现设备入库登记 设备领用与归还登记 设备维修登记 设备变更登记等功能模块, 并且每一个模块还需要划分多个子模块 ; 使用各自不同的结构体来储存不同的登记信息 ; 使用链表来实现各种登记信息的添加 删除 查询 修改等操作 ; 使用文件来保存数据, 以便下次运行时可以自动将数据从文件读取到链表中 5.1 实践目的 (1) 掌握带头节点的链表的工作原理和处理方式

More information

数据结构 Data Structure

数据结构 Data Structure 第三章 : 线性表 线性表 定义 : 线性表 L 是 n 个数据元素 a 0,a, a n- 的有限序列, 记作 L=(a 0,a, a n- ) 其中元素个数 n(n 0) 定义为表 L 的长度 当 n=0 时,L 为空表, 记作 ( ) 特性 : 在表中, 除第一个元素 a 0 外, 其他每一个元素 a i 有一个且仅有 一个直接前驱 a i- 除最后一个元素 a n- 外, 其他每一个元素 a

More information

目 录 目 录 前言 第 章 绪论 知识点串讲 典型例题详解 课后习题与解答 第 章 线性表 知识点串讲 典型例题详解 课后习题与解答 第 章 栈和队列 知识点串讲 典型例题详解 课后习题与解答 第 章 串 知识点串讲 典型例题详解 课后习题与解答 第 章 数组和广义表 知识点串讲 典型例题详解 课

目 录 目 录 前言 第 章 绪论 知识点串讲 典型例题详解 课后习题与解答 第 章 线性表 知识点串讲 典型例题详解 课后习题与解答 第 章 栈和队列 知识点串讲 典型例题详解 课后习题与解答 第 章 串 知识点串讲 典型例题详解 课后习题与解答 第 章 数组和广义表 知识点串讲 典型例题详解 课 数据结构 语言版 例题详解与课程设计指导 主 编 秦 锋 袁志祥副主编 陈学进 王森玉郑 啸 程泽凯 合肥 目 录 目 录 前言 第 章 绪论 知识点串讲 典型例题详解 课后习题与解答 第 章 线性表 知识点串讲 典型例题详解 课后习题与解答 第 章 栈和队列 知识点串讲 典型例题详解 课后习题与解答 第 章 串 知识点串讲 典型例题详解 课后习题与解答 第 章 数组和广义表 知识点串讲 典型例题详解

More information

新・明解C言語入門編『索引』

新・明解C言語入門編『索引』 !... 75!=... 48 "... 234 " "... 9, 84, 240 #define... 118, 213 #include... 148 %... 23 %... 23, 24 %%... 23 %d... 4 %f... 29 %ld... 177 %lf... 31 %lu... 177 %o... 196 %p... 262 %s... 242, 244 %u... 177

More information

Guava学习之CharSequenceReader

Guava学习之CharSequenceReader CharSequenceReader 类是以 CharSequence 的形式读取字符 CharSequenceReader 类继承自 Reader 类, 除了 remaining() hasremaining() 以及 checkopen() 函数之后, 其他的函数都是重写 Reader 类中的函数 CharSequenceReader 类声明没有用 public 关键字, 所以我们暂时还不能调用这个类

More information

2 线性表 Linear List 姜玻 2 线性表 Linear List 2.1 线性表的定义和 基本操作 2.2 线性表的实现 线性表的顺序存储 姜玻 教育科学与技术学院 数字媒体技术系 单链表 带表头结点的单链表 单循环链表 双向链

2 线性表 Linear List 姜玻 2 线性表 Linear List 2.1 线性表的定义和 基本操作 2.2 线性表的实现 线性表的顺序存储 姜玻 教育科学与技术学院 数字媒体技术系 单链表 带表头结点的单链表 单循环链表 双向链 2.1 线性表的定义和 基本操作 2.的实现 教育科学与技术学院 数字媒体技术系 前情提要 程序 = 数据结构 + 算法何为数据结构, 相关的术语逻辑结构存储结构运算抽象数据类型 (Abstract Data Type,ADT) C++ 定义和实现何为算法, 其特点和设计要求算法的时间复杂度 ( 大 O 表示 ) 算法的空间复杂度 2.的实现 前情提要 ADT Stack{ 数据 : 0 个或多个元素的序列

More information

Microsoft PowerPoint - Slides03_第二章 线性表.ppt [兼容模式]

Microsoft PowerPoint - Slides03_第二章 线性表.ppt [兼容模式] 第二章线性表 定义 基本操作 实现 顺序存储 链式存储 应用 多项式 线性表 (Linear List) 定义 线性表是 n ( 0) 个数据元素的有限序列, 记作 (a 1, a 2,, a n ) a i 是表中数据元素,n 是表长度 假定 : 各元素的数据类型相同 原则上 : 线性表中, 表元素的数据类型可以不相同 采用的存储表示可能会对元素的数据类型有限制 特点 除第一个元素外, 其他每一个元素有一个且仅有一个直接前驱

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,

More information

Microsoft PowerPoint - 第+2+章+线性表[check].ppt [兼容模式]

Microsoft PowerPoint - 第+2+章+线性表[check].ppt [兼容模式] 教学内容 1 线性表的定义和性质及基本运算 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 多项式的代数运算 线性结构的特点 : 数据元素的非空有限集 存在唯一的一个被称作 第一个 的数据元素 ; 存在唯一的一个被称作 最后一个 的数据元素 ; 除第一个之外的数据元素均只有一个前驱 ; 除最后一个之外的数据元素均只有一个后继 例 : 法学系 8523101 第一个 数据元素 国贸系 8522105

More information

新・解きながら学ぶC言語

新・解きながら学ぶC言語 330!... 67!=... 42 "... 215 " "... 6, 77, 222 #define... 114, 194 #include... 145 %... 21 %... 21 %%... 21 %f... 26 %ld... 162 %lf... 26 %lu... 162 %o... 180 %p... 248 %s... 223, 224 %u... 162 %x... 180

More information

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3 浙江大学 C 程序设计及实验 试题卷 2002-2003 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:30-10:30 注意 : 答题内容必须写在答题卷上, 写在本试题卷上无效 一. 单项选择题 ( 每题 1 分, 共 10 分 ) 1. 下列运算符中, 优先级最低的是 A.

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

新版 明解C言語入門編

新版 明解C言語入門編 328, 4, 110, 189, 103, 11... 318. 274 6 ; 10 ; 5? 48 & & 228! 61!= 42 ^= 66 _ 82 /= 66 /* 3 / 19 ~ 164 OR 53 OR 164 = 66 ( ) 115 ( ) 31 ^ OR 164 [] 89, 241 [] 324 + + 4, 19, 241 + + 22 ++ 67 ++ 73 += 66

More information

没有幻灯片标题

没有幻灯片标题 指针作为函数参数 : 原因 : 1 需要修改一个或多个值,( 用 return 语句不能解决问题 ) 2 执行效率的角度 使用方法 : 在函数原型以及函数首部中需要声明能够接受指针值的形参, 具体的写法为 : 数据类型 * 形参名 如果有多个指针型形参, 则用逗号分隔, 例如 : void swap(int *p1, int *p2) 它说明了形参 p1 p2 是指向整型变量的指针 在函数调用时,

More information

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 1 TEMPLATE 1 Template 描述 使用模板函数求最大值 使用如下 main 函数对程序进行测试 int main() { double a, b; cin >> a >> b; cout c >> d; cout

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

树的非递归中序和层次遍历实现

树的非递归中序和层次遍历实现 相信大家对树的各种递归的遍历很了解, 利用递归使得代码变得简单而且比较好理解, 但是利用递归是需要代价的, 特别是当递归层次比较深的时候, 可能会导致递归栈溢出 而且递归一般运行速度比较慢, 那么这种情况下, 我们就可以采用非递归来实现, 非递归相对递归来说, 代码相对比较难理解, 而且代码量也一般比较多, 可是它的执行效率却是很不错的 在树的中序非递归遍历中需要用到栈, 在层次遍历中需要用到队列,

More information

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢   学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: 51141201063@ecnu.cn 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Java 类型 引用 不可变类型 对象存储位置 作用域 OOP

More information

download.kaoyan.com_2006ÄêÌì½ò¹¤Òµ´óѧ¸ß¼¶ÓïÑÔ³ÌÐòÉè¼Æ£¨409£©¿¼ÑÐÊÔÌâ

download.kaoyan.com_2006ÄêÌì½ò¹¤Òµ´óѧ¸ß¼¶ÓïÑÔ³ÌÐòÉè¼Æ£¨409£©¿¼ÑÐÊÔÌâ 考生注意 : 本试卷共七大题, 满分 150 分 考试时间为 3 小时 ; 所有答案均写在答题纸上 ( 注明题号 ), 在此答题一律无效无效 一 选择题 ( 本题共 20 小题, 每小题 2 分, 满分 40 分 ) 1 char ch 1 2 A 0

More information

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式] 指针 Pointers 变量指针与指针变量 Pointer of a variable 变量与内存 (Variables and Memory) 当你声明一个变量时, 计算机将给该变量一个内存, 可以存储变量的值 当你使用变量时, 计算机将做两步操作 : - 根据变量名查找其对应的地址 ; - 通过地址对该地址的变量内容进行读 (retrieve) 或写 (set) 变量的地址称为变量的指针! C++

More information

epub 33-8

epub 33-8 8 1) 2) 3) A S C I I 4 C I / O I / 8.1 8.1.1 1. ANSI C F I L E s t d i o. h typedef struct i n t _ f d ; i n t _ c l e f t ; i n t _ m o d e ; c h a r *_ n e x t ; char *_buff; /* /* /* /* /* 1 5 4 C FILE

More information

_汪_文前新ok[3.1].doc

_汪_文前新ok[3.1].doc 普 通 高 校 本 科 计 算 机 专 业 特 色 教 材 精 选 四 川 大 学 计 算 机 学 院 国 家 示 范 性 软 件 学 院 精 品 课 程 基 金 青 年 基 金 资 助 项 目 C 语 言 程 序 设 计 (C99 版 ) 陈 良 银 游 洪 跃 李 旭 伟 主 编 李 志 蜀 唐 宁 九 李 涛 主 审 清 华 大 学 出 版 社 北 京 i 内 容 简 介 本 教 材 面 向

More information

试卷代号 :1253 座位号 E 口 国家开放大学 ( 中央广播电视大学 )2014 年秋季学期 " 开放本科 " 期末考试 C 语言程序设计 A 试题 2015 年 1 月 E 四! 五 总分! 一 单选题 ( 每小题 2 分, 共 20 分 ) 1. 由 C 语言源程序文件编译而成的目标文件的默

试卷代号 :1253 座位号 E 口 国家开放大学 ( 中央广播电视大学 )2014 年秋季学期  开放本科  期末考试 C 语言程序设计 A 试题 2015 年 1 月 E 四! 五 总分! 一 单选题 ( 每小题 2 分, 共 20 分 ) 1. 由 C 语言源程序文件编译而成的目标文件的默 试卷代号 :1253 座位号 E 口 国家开放大学 ( 中央广播电视大学 )2014 年秋季学期 " 开放本科 " 期末考试 C 语言程序设计 A 试题 2015 年 1 月 E 四! 五 总分! 一 单选题 ( 每小题 2 分, 共 20 分 ) 1. 由 C 语言源程序文件编译而成的目标文件的默认扩展名为 ( ) A. cpp B. c C. exe D. obj 2. 设 x 和 y 均为逻辑值,

More information

《计算概论》课程 第十九讲 C 程序设计语言应用

《计算概论》课程 第十九讲  C 程序设计语言应用 计算概论 A 程序设计部分 字符数组与字符串 李戈 北京大学信息科学技术学院软件研究所 lige@sei.pku.edu.cn 字符数组的定义 #include int main() char a[10] = 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ; for (int i = 0; i < 10; i++) cout

More information

C/C++语言 - 运算符、表达式和语句

C/C++语言 - 运算符、表达式和语句 C/C++ Table of contents 1. 2. 3. 4. C C++ 5. 6. 7. 1 i // shoe1.c: # include # define ADJUST 7. 64 # define SCALE 0. 325 int main ( void ) { double shoe, foot ; shoe = 9. 0; foot = SCALE * shoe

More information

试卷代号 : 座位号 CD 中央广播电视大学 学年度第二学期 " 开放本科 " 期末考试 数据结构 ( 本 ) 试题 I 题号 - - I 二 l 三 l 四 l 总 分 分数 I I I I I I 2009 年 7 月 得分 评卷人 I I I 一

试卷代号 : 座位号 CD 中央广播电视大学 学年度第二学期  开放本科  期末考试 数据结构 ( 本 ) 试题 I 题号 - - I 二 l 三 l 四 l 总 分 分数 I I I I I I 2009 年 7 月 得分 评卷人 I I I 一 试卷代号 : 1 2 5 2 座位号 CD 中央广播电视大学 2 0 0 8-2 0 0 9 学年度第二学期 " 开放本科 " 期末考试 数据结构 ( 本 ) 试题 I 题号 - - I 二 l 三 l 四 l 总 分 分数 I I I I I I 2009 年 7 月 得分 评卷人 I I I 一 单项选择题 ( 每小题 2 分如 崎盯扫, 共 3t 3ω O 1. 针对线性表, 在存储后如果最常用的操作是取第

More information

C C

C C C C 2017 3 8 1. 2. 3. 4. char 5. 2/101 C 1. 3/101 C C = 5 (F 32). 9 F C 4/101 C 1 // fal2cel.c: Convert Fah temperature to Cel temperature 2 #include 3 int main(void) 4 { 5 float fah, cel; 6 printf("please

More information

C/C++ - 函数

C/C++ - 函数 C/C++ Table of contents 1. 2. 3. & 4. 5. 1 2 3 # include # define SIZE 50 int main ( void ) { float list [ SIZE ]; readlist (list, SIZE ); sort (list, SIZE ); average (list, SIZE ); bargragh

More information

C++ 程序设计 OJ4 - 参考答案 MASTER 2017 年 5 月 21 日 1

C++ 程序设计 OJ4 - 参考答案 MASTER 2017 年 5 月 21 日 1 C++ 程序设计 OJ4 - 参考答案 MASTER 2017 年 5 月 21 日 1 1 SWAP 1 Swap 题目描述 用函数模板的方式实现对不同数据类型的数组中的数据进行输入 从小到大排序和输出 使用如下主函数测试你的模板设计一个函数模板 Swap, 实现任意数据类型的两个数据的交换, 分别用 int 型 double 型和 char 型的数据进行测试 main 函数如下 : int main()

More information

C/C++ - 结构体、共用体、枚举体

C/C++ - 结构体、共用体、枚举体 C/C++ Table of contents 1. 2. 3. 4. 5. 6. 7. 8. 1 C C (struct) C 2 C C (struct) C 2 i // book.c: # include < stdio.h> # define MAX_ TITLE 41 # define MAX_ AUTHOR 31 struct book { char title [ MAX_ TITLE

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc 2 5 8 11 0 1. 13 2. 15 3. 18 1 1. 22 2. 25 3. 27 2 1. 35 2. 38 3. 41 4. 43 5. 48 6. 50 3 1. 56 2. 59 3. 63 4. 65 5. 69 13 22 35 56 6. 74 7. 82 8. 84 9. 87 10. 97 11. 102 12. 107 13. 111 4 114 1. 114 2.

More information

第3章.doc

第3章.doc 3 3 3 3.1 3 IT Trend C++ Java SAP Advantech ERPCRM C++ C++ Synopsys C++ NEC C C++PHP C++Java C++Java VIA C++ 3COM C++ SPSS C++ Sybase C++LinuxUNIX Motorola C++ IBM C++Java Oracle Java HP C++ C++ Yahoo

More information

Microsoft PowerPoint - C语言课件-9-结构体.pptx

Microsoft PowerPoint - C语言课件-9-结构体.pptx 第九章结构体 郎大鹏 第九章结构体 9.1 结构体类型的声明方法 9.2 结构体类型变量的定义与使用 9.3 结构体数组 9.4 编程举例 9.5 习题 9.1 结构体类型的声明方法 结构体声明的语法形式如下 : struct 结构体标识符 成员变量列表 ; }; 例如, 为了描述班级 ( 假设仅仅包括班级编号 专业 人数等信息 ), 可以声明如下的结构体类型 struct Class char Code[10];

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 第 12 章再谈指针 本章的基本内容是 : 指针与数组 指针与结构体 动态存储分配 由于指针可以直接对内存进行操作, 所以指针的功能非常 强大 正确灵活地使用指针可以有效地表示复杂的数据结 构, 并可动态分配内存空间, 提高程序的运行效率 任务 12.1 判断回文 问题 输入一个字符串, 判断该字符串是否为回文 ( 首尾对称的字句, 例如 abcba abba 均为回文 ) 要求用指针实现 想法 设两个指针变量

More information

试卷格式

试卷格式 一 基本知识题 (10 分 ) 1.1. 已知定义 :int a=0; 请指出以下不会产生死循环的控制结构 A)for( ; ; ) if(a) break; B)for( ; ; a=0) if(a) break; C)for( ; ; ) if(a) continue; D)for( ; a=0 ; ) if(a) break; 1.2. 请指出正确描述实参和形参关系的命题 A) 如果实参是数组名,

More information

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取将导致上次获取的 access_token 失效 接入方可以使用 AppID 和 AppSecret

More information

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf (%d, & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf (%d %d 2013 18 ( ) 1. C pa.c, pb.c, 2. C++ pa.cpp, pb.cpp, Compilation Error cin scanf Time Limit Exceeded 1: A 5 B 5 C 5 D 5 E 5 F 5 1 2013 C 1 # include 2 int main ( void ) 3 { 4 int cases, a, b,

More information

プログラムの設計と実現II

プログラムの設計と実現II UNIX C ls mkdir man http://www.tj.chiba-u.jp/lecture/prog2/ Ctrl+x, Ctrl+s ( )..[4]% gcc Wall o hoge hoge.c..[5]%./hoge 1 : 1 2 : 2 3 : 3 4 : 0 6..[6]% (! )..[4]% gcc Wall o hoge hoge.c..[5]%!g gcc Wall

More information

新版 明解C++入門編

新版 明解C++入門編 511!... 43, 85!=... 42 "... 118 " "... 337 " "... 8, 290 #... 71 #... 413 #define... 128, 236, 413 #endif... 412 #ifndef... 412 #if... 412 #include... 6, 337 #undef... 413 %... 23, 27 %=... 97 &... 243,

More information

* 4 6 R P r p . 1 2 3 4 7 89bk 6 5 1 2 3 4 5 6 7 8 9 0 bk r bl bm bn^ bo bl br bq bpbo bn bm [ ] [ ] [ ] bp 8 2 4 6 bq p [ ] [SET] br clckbt bs bs bt ck cl. 1 2 1 2+- 3 3 . 1 2 3 4 5 6 7 8 9 bk bl bm

More information

Microsoft PowerPoint - DS_Ch5.ppt [兼容模式]

Microsoft PowerPoint - DS_Ch5.ppt [兼容模式] 数据结构 Ch.5 数组和广义表 计算机学院 肖明军 Email: xiaomj@ustc.edu.cn http://staff.ustc.edu.cn/~xiaomj 多维数组 是最易处理的非线性结构 因为各元素类型一致, 各维上下界固定, 所以它最容易线性化, 故可看做是线性表的拓广 例如 : 二维数组可以看做是由列向量组成的线性表 1. 结构特性 例 : 二维数组, 它属于两个向量 ;i th

More information

第 3 章补充案例 案例 3-1 统计成绩最大值和最小值 一 案例描述 1 考核知识点数组的创建 2 练习目标 掌握创建数组的方式 了解 Array.length 求数组长度 3 需求分析输入小明的 5 门成绩, 计算出总分, 平均分 最高分, 最低分 4 案例分析 1) 效果如图 3-1 所示 图

第 3 章补充案例 案例 3-1 统计成绩最大值和最小值 一 案例描述 1 考核知识点数组的创建 2 练习目标 掌握创建数组的方式 了解 Array.length 求数组长度 3 需求分析输入小明的 5 门成绩, 计算出总分, 平均分 最高分, 最低分 4 案例分析 1) 效果如图 3-1 所示 图 第 3 章补充案例 案例 3-1 统计成绩最大值和最小值 1 考核知识点数组的创建 掌握创建数组的方式 了解 Array.length 求数组长度 3 需求分析输入小明的 5 门成绩, 计算出总分, 平均分 最高分, 最低分 1) 效果如图 3-1 所示 图 3-1 计算结果展示 a) 定义一个数组 arr, 存放 5 门成绩 b) 定义总分变量 sum=0 c) 定义最高分变量 max=0 d)

More information

C++ 程序设计 OJ4 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 OJ4 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 OJ4 - 参考答案 MASTER 2019 年 5 月 3 日 1 1 MYQUEUE 1 MyQueue 题目描述 设计一个 MyQueue 类模板, 类模板说明如下 : template class MyQueue; template std::ostream & operator

More information

华恒家庭网关方案

华恒家庭网关方案 LINUX V1.5 1 2 1 2 LINUX WINDOWS PC VC LINUX WINDOWS LINUX 90% GUI LINUX C 3 REDHAT 9 LINUX PC TFTP/NFS http://www.hhcn.com/chinese/embedlinux-res.html minicom NFS mount C HHARM9-EDU 1 LINUX HHARM9-EDU

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information

Microsoft PowerPoint - 1绪论.ppt [兼容模式]

Microsoft PowerPoint - 1绪论.ppt [兼容模式] 1 绪论 董洪伟 http://hwdong.com 主要内容 什么是数据结构 定义 内容 基本术语 数据 : 数据对象 数据元素 数据项 数据结构 : 逻辑结构 物理结构 抽象数据类型 定义 表示 算法和算法分析 算法的概念 算法复杂度 什么是数据结构 程序 = 数据结构 + 算法 Pascal 之父,Niklaus Wirth 数据结构 : 问题的数学模型 数据表示 算法 : 处理问题的策略 数据处理

More information

untitled

untitled A, 3+A printf( ABCDEF ) 3+ printf( ABCDEF ) 2.1 C++ main main main) * ( ) ( ) [ ].* ->* ()[] [][] ** *& char (f)(int); ( ) (f) (f) f (int) f int char f char f(int) (f) char (*f)(int); (*f) (int) (

More information

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf (%d, & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9 201 201 21 ( ) 1. C pa.c, pb.c, 2. C++ pa.cpp, pb.cpp Compilation Error long long cin scanf Time Limit Exceeded 1: A 1 B 1 C 5 D RPG 10 E 10 F 1 G II 1 1 201 201 C 1 # include 2 int main ( void

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 STC 单片机复杂数据结构 主讲 : 何宾 Email:hebin@mail.buct.edu.cn 2016.03 结构类型定义的格式为 : struct 结构名 } 其中 : 结构元素列表 结构 -- 结构类型的定义 结构元素列表为不同数据类型的列表 结构 -- 结构类型的定义 例 16-1 结构体的声明例子 struct student char name[30]; char gender;

More information

网C试题(08上).doc

网C试题(08上).doc 学习中心 姓名 学号 西安电子科技大学网络与继续教育学院 高级语言程序设计 (C) 全真试题 ( 闭卷 90 分钟 ) 题号一二三总分 题分 60 20 20 得分 一 单项选择题 ( 每小题 3 分, 共 60 分 ) 1.C 语言程序的基本单位是 A) 程序行 B) 语句 C) 函数 D) 字符 2. 下列四组选项中, 均是不合法的用户标识符的选项是 A)A B)getc C)include D)while

More information

四 读算法 ( 每题 7 分, 共 14 分 ) 1. (1) 查询链表的尾结点 (2) 将第一个结点链接到链表的尾部, 作为新的尾结点 (3) 返回的线性表为 (a 2,a 3,,a n,a 1 ) 2. 递归地后序遍历链式存储的二叉树 五 法填空 ( 每空 2 分, 共 8 分 ) true B

四 读算法 ( 每题 7 分, 共 14 分 ) 1. (1) 查询链表的尾结点 (2) 将第一个结点链接到链表的尾部, 作为新的尾结点 (3) 返回的线性表为 (a 2,a 3,,a n,a 1 ) 2. 递归地后序遍历链式存储的二叉树 五 法填空 ( 每空 2 分, 共 8 分 ) true B 数据结构试卷 ( 一 ) 参考答案 一 选择题 ( 每题 2 分, 共 20 分 ) 1.A 2.D 3.D 4.C 5.C 6.D 7.D 8.C 9.D 10.A 二 填空题 ( 每空 1 分, 共 26 分 ) 1. 正确性 易读性 强壮性 高效率 2. O(n) 3. 9 3 3 4. -1 3 4 X * + 2 Y * 3 / - 5. 2n n-1 n+1 6. e 2e 7. 有向无回路

More information

untitled

untitled Introduction to Programming ( 數 ) Lecture 3 Spring 2005 March 4, 2005 Lecture 2 Outline 數 料 If if 狀 if 2 (Standard Output, stdout): 料. ((Standard Input, stdin): 料. 類 數 數 數 說 printf 見 數 puts 串 數 putchar

More information

C/C++ - 字符输入输出和字符确认

C/C++ - 字符输入输出和字符确认 C/C++ Table of contents 1. 2. getchar() putchar() 3. (Buffer) 4. 5. 6. 7. 8. 1 2 3 1 // pseudo code 2 read a character 3 while there is more input 4 increment character count 5 if a line has been read,

More information

C/C++ 语言 - 循环

C/C++ 语言 - 循环 C/C++ Table of contents 7. 1. 2. while 3. 4. 5. for 6. 8. (do while) 9. 10. (nested loop) 11. 12. 13. 1 // summing.c: # include int main ( void ) { long num ; long sum = 0L; int status ; printf

More information

C

C C 14 2017 5 31 1. 2. 3. 4. 5. 2/101 C 1. ( ) 4/101 C C ASCII ASCII ASCII 5/101 C 10000 00100111 00010000 ASCII 10000 31H 30H 30H 30H 30H 1 0 0 0 0 0 ASCII 6/101 C 7/101 C ( ) ( ) 8/101 C UNIX ANSI C 9/101

More information

C++ 程式設計

C++ 程式設計 C C 料, 數, - 列 串 理 列 main 數串列 什 pointer) 數, 數, 數 數 省 不 不, 數 (1) 數, 不 數 * 料 * 數 int *int_ptr; char *ch_ptr; float *float_ptr; double *double_ptr; 數 (2) int i=3; int *ptr; ptr=&i; 1000 1012 ptr 數, 數 1004

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 9 [P.11] : Dev C++ [P.12] : http://c.feis.tw [P.13] [P.14] [P.15] [P.17] [P.23] Dev C++ [P.24] [P.27] [P.34] C / C++ [P.35] 10 C / C++ C C++ C C++ C++ C ( ) C++

More information

untitled

untitled 不 料 料 例 : ( 料 ) 串 度 8 年 數 串 度 4 串 度 數 數 9- ( ) 利 數 struct { ; ; 數 struct 數 ; 9-2 數 利 數 C struct 數 ; C++ 數 ; struct 省略 9-3 例 ( 料 例 ) struct people{ char name[]; int age; char address[4]; char phone[]; int

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

38 47995529 威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 1059003070 號 39 47995534 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民

38 47995529 威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 1059003070 號 39 47995534 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民 1 08414159 惠 鴻 眼 鏡 行 桃 園 市 中 壢 區 福 德 里 中 華 路 一 段 186 號 1 樓 30,000 獨 資 宋 耀 鴻 105/04/27 府 經 登 字 第 1059003866 號 2 17891110 承 元 冷 氣 空 調 工 程 行 桃 園 市 桃 園 區 中 德 里 國 際 路 1 段 98 巷 50 號 2 樓 之 4 200,000 獨 資 詹 安 平

More information

3. 給 定 一 整 數 陣 列 a[0] a[1] a[99] 且 a[k]=3k+1, 以 value=100 呼 叫 以 下 兩 函 式, 假 設 函 式 f1 及 f2 之 while 迴 圈 主 體 分 別 執 行 n1 與 n2 次 (i.e, 計 算 if 敘 述 執 行 次 數, 不

3. 給 定 一 整 數 陣 列 a[0] a[1] a[99] 且 a[k]=3k+1, 以 value=100 呼 叫 以 下 兩 函 式, 假 設 函 式 f1 及 f2 之 while 迴 圈 主 體 分 別 執 行 n1 與 n2 次 (i.e, 計 算 if 敘 述 執 行 次 數, 不 1. 右 側 程 式 正 確 的 輸 出 應 該 如 下 : * *** ***** ******* ********* 在 不 修 改 右 側 程 式 之 第 4 行 及 第 7 行 程 式 碼 的 前 提 下, 最 少 需 修 改 幾 行 程 式 碼 以 得 到 正 確 輸 出? (A) 1 (B) 2 (C) 3 (D) 4 1 int k = 4; 2 int m = 1; 3 for (int

More information

[改訂新版]C言語による標準アルゴリズム事典

[改訂新版]C言語による標準アルゴリズム事典 iii C 1991 SEND + MORE = MONEY C 100 2003 Java 2003 27 PC-9800 C BMP SVG EPS BMPSVG WindowsMacLinux Web iv int main() int main(void) EXIT_SUCCESS 0 https://github.com/okumuralab/ algo-c TEX TEX PDF PDF

More information

C++ 程序设计 实验 3 - 参考答案 MASTER 2017 年 5 月 21 日 1

C++ 程序设计 实验 3 - 参考答案 MASTER 2017 年 5 月 21 日 1 C++ 程序设计 实验 3 - 参考答案 MASTER 2017 年 5 月 21 日 1 1 圆 1 圆 设计圆类 包含 包含基本属性和基本属性访问接口 计算面积和周长接口 2 1 圆 1 #include 2 using namespace std ; 3 c l a s s CCircle 4 { 5 p r i v a t e : 6 double r ; 7 const

More information

2013 C 1 #include <stdio.h> 2 int main(void) 3 { 4 int cases, i; 5 long long a, b; 6 scanf("%d", &cases); 7 for (i = 0; i < cases; i++) 8 { 9 scanf("%

2013 C 1 #include <stdio.h> 2 int main(void) 3 { 4 int cases, i; 5 long long a, b; 6 scanf(%d, &cases); 7 for (i = 0; i < cases; i++) 8 { 9 scanf(% 2013 ( 28 ) ( ) 1. C pa.c, pb.c, 2. C++ pa.cpp, pb.cpp Compilation Error long long cin scanf Time Limit Exceeded 1: A 10 B 1 C 1 D 5 E 5 F 1 G II 5 H 30 1 2013 C 1 #include 2 int main(void) 3

More information

C语言的应用.PDF

C语言的应用.PDF AVR C 9 1 AVR C IAR C, *.HEX, C,,! C, > 9.1 AVR C MCU,, AVR?! IAR AVR / IAR 32 ALU 1KBytes - 8MBytes (SPM ) 16 MBytes C C *var1, *var2; *var1++ = *--var2; AVR C 9 2 LD R16,-X ST Z+,R16 Auto (local

More information

untitled

untitled CHAPTER 02 2 CHAPTER 2-1 2-4 2-2 2-5 2-3 2-6 2-1 2-1-1 2-2 02 int A[3] = {10, 20, 30; A[0] 10 A[1] 20 A[2] 30 int *pa[3], A[3]; C 3 pa pa[0]pa[1]pa[2] 3 A A[0]A[1]A[2] 3 A A[0] A + i A[i] A + i &A[i]*(A

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

C/C++ - 数组与指针

C/C++ - 数组与指针 C/C++ Table of contents 1. 2. 3. 4. 5. 6. 7. 8. 1 float candy [ 365]; char code [12]; int states [50]; 2 int array [6] = {1, 2, 4, 6, 8, 10}; 3 // day_mon1.c: # include # define MONTHS 12 int

More information

python内存管理

python内存管理 Python 级内存管理 - xiaorui.cc Object-specific allocators [ int ] [ dict ] [ list ]... [ string ] Python core +3 [ Python's object allocator ]

More information

《C语言程序设计》教材习题参考答案

《C语言程序设计》教材习题参考答案 教材名称 : C 语言程序设计 ( 第 1 版 ) 黄保和 江弋编著清华大学出版社 ISBN: 978-7-302-13599-9, 红色封面答案制作时间 :2011 年 2 月 -5 月一 选择题 1. 以下数组定义中, 错误的是 :C)int a[3]=1,2,3,4; 2. 以下数组定义中, 正确的是 :B) int a[][2]=1,2,3,4; 3. 设有定义 int a[8][10];,

More information

Microsoft PowerPoint - 01_Introduction.ppt

Microsoft PowerPoint - 01_Introduction.ppt Hello, World C 程序设计语言 第 1 章章观其大略 孙志岗 sun@hit.edu.cn http://sunner.cn prf("hello,, world\n"); 超级无敌考考你 : 如何把 hello 和 world 分别打印在两行? 2004-12-19 A Tutorial Introduction 2 hello.c 打印华氏温度与摄氏温度对照表 计算公式 : C=(5/9)(

More information

C++ 程序设计 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 1 PERSON 1 Person 题目描述 编写程序, 定义一个基类 Person, 包含 name 和 age 两个数据成员 ; 再由它派生出学生类 Student 和教师类 Teacher, 其中学生类添加学号 no 数据, 教师类添加职称 title 数据 ; 要求每个类均有构造函数 析构函数和显示数据的函数

More information

中北大学常规事项财务报销操作指南

中北大学常规事项财务报销操作指南 中 北 大 学 常 规 事 项 财 务 报 销 操 作 指 南 一 办 公 费 报 销 指 南 定 义 : 办 公 费 是 单 位 购 买 按 财 务 会 计 制 度 规 定 不 符 合 固 定 资 产 标 准 的 日 常 办 公 用 品 书 报 杂 志 等 支 出 通 俗 讲 是 指 办 公 场 所 使 用 的 低 值 易 耗 品 办 公 用 品 的 类 别 : 纸 薄 类 笔 尺 类 装 订 类

More information

C

C C 2017 4 1 1. 2. while 3. 4. 5. for 6. 2/161 C 7. 8. (do while) 9. 10. (nested loop) 11. 12. 3/161 C 1. I 1 // summing.c: 2 #include 3 int main(void) 4 { 5 long num; 6 long sum = 0L; 7 int status;

More information

立 志 于 打 造 最 贴 近 考 生 实 际 的 辅 导 书 计 算 机 考 研 之 数 据 结 构 高 分 笔 记 率 辉 编 著 周 伟 张 浩 审 核 讨 论 群 :15945769

立 志 于 打 造 最 贴 近 考 生 实 际 的 辅 导 书 计 算 机 考 研 之 数 据 结 构 高 分 笔 记 率 辉 编 著 周 伟 张 浩 审 核 讨 论 群 :15945769 立 志 于 打 造 最 贴 近 考 生 实 际 的 辅 导 书 计 算 机 考 研 之 数 据 结 构 高 分 笔 记 率 辉 编 著 周 伟 张 浩 审 核 讨 论 群 :15945769 前 言 在 计 算 机 统 考 的 四 门 专 业 课 中, 最 难 拿 高 分 的 就 是 数 据 结 构 但 是 这 门 课 本 身 的 难 度 并 不 是 考 生 最 大 的 障 碍, 真 正 的 障 碍

More information

FY.DOC

FY.DOC 高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主

More information

通过Hive将数据写入到ElasticSearch

通过Hive将数据写入到ElasticSearch 我在 使用 Hive 读取 ElasticSearch 中的数据 文章中介绍了如何使用 Hive 读取 ElasticSearch 中的数据, 本文将接着上文继续介绍如何使用 Hive 将数据写入到 ElasticSearch 中 在使用前同样需要加入 elasticsearch-hadoop-2.3.4.jar 依赖, 具体请参见前文介绍 我们先在 Hive 里面建个名为 iteblog 的表,

More information

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023)

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023) ( CIP) /. :, 2005. 2 ( ) ISBN 7-5624-3339-9.......... TP311. 1 CIP ( 2005) 011794 : : : : * : : 174 ( A ) :400030 : ( 023) 65102378 65105781 : ( 023) 65103686 65105565 : http: / /www. cqup. com. cn : fxk@cqup.

More information

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco Windows RTEMS 1 Danilliu MMI TCP/IP 80486 QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos ecos Email www.rtems.com RTEMS ecos RTEMS RTEMS Windows

More information

工程项目进度管理 西北工业大学管理学院 黄柯鑫博士 甘特图 A B C D E F G 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 甘特图的优点 : 直观明了 ( 图形化概要 ); 简单易懂 ( 易于理解 ); 应用广泛 ( 技术通用 ) 甘特图的缺点 : 不能清晰表示活动间的逻辑关系 WBS 责任分配矩阵 ( 负责〇审批

More information