3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用

Slides:



Advertisements
Similar presentations
数据结构概论 第2章 线性表 董黎刚 浙江工商大学信电学院
Advertisements

第三章 鏈結串列 Linked List.
全力以赴的德忠精神 人力资源部王丽玲主任,从员工关系的工作,到招聘工作,再到现在的薪酬工作,不管在哪个岗位,她总是一丝不苟,尽职尽责。
计算机硕士专业基础—C语言 赵海英
第8章 查找 在英汉字典中查找某个英文单词的中文解释;在新华字典中查找某个汉字的读音、含义;在对数表、平方根表中查找某个数的对数、平方根;邮递员送信件要按收件人的地址确定位置等等。可以说查找是为了得到某个信息而常常进行的工作。 计算机、计算机网络使信息查询更快捷、方便、准确。要从计算机、计算机网络中查找特定的信息,就需要在计算机中存储包含该特定信息的表。如要从计算机中查找英文单词的中文解释,就需要存储类似英汉字典这样的信息表,以及对该表进行的查找操作。本章将讨论的问题即是“信息的存储和查找”。
第十章 内部排序 10.1 概述 10.2 插入排序 直接插入排序 其他插入排序 希尔排序
数据结构 第6章 树和二叉树 什么是树和二叉树?? 二叉树的遍历 数据结构.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第2章 线性表 2.1 线性表的概念及运算 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 一元多项式的表示及相加.
C语言基础——指针的高级应用 Week 05.
数据结构与算法 数据结构与算法实验
運輸與空間的交互作用 運輸發展的階段 一、分散的港口 二、侵入路線 三、發展支線 四、初步相互連結 五、完全相互連結 六、高度優越的幹線
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
第3章 栈和队列 3.1 栈 3.2 队列 3.3 应用.
單向鏈結串列 Singly Linked Lists.
第2章 线性表 线性结构 是一个数据元素的有序集合。.
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
第11章 查找 主要知识点 查找的基本概念 静态查找表 动态查找表 哈希表.
第8章 排序.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
第九章 排序 9.1排序的基本概念 9.2简单排序方法(复杂度 O(n2)) 9.3先进排序方法(复杂度 O(nLogn))
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
第2章 线性表(三) 1/.
第12章 樹狀搜尋結構 (Search Trees)
第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 线性表的应用 2.5 有序表 本章小结.
第3章 栈和队列(二) 1/.
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第十章 C高级程序应用—链表* 10.1链表的基本概念 10.2单向链表 10.3双向链表 10.4应用举例.
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
本章重点难点 重点:顺序查找、二分查找、二叉排序树查找以及散列表查找的基本思想和算法实现。
第 3 讲 线性表(一).
第3章 栈和队列(一).
数据结构 Data Structure 中南大学 主讲人:王国军,郑瑾 中南大学信息院计科系
第二章 线性表.
第一章 绪论.
数 据 结 构 Ch.4 串 计 算 机 学 院 肖明军
五、链 表 1、单链表 2、双向链表 3、链表应用.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
内容回顾 线性表的定义和特点 线性表的顺序存储及查找、插入和删除.
第9章 内部排序 9.1 概述 9.2 插入排序 9.3 快速排序 9.4 选择排序 9.5 归并排序 9.6 基数排序
第四讲 线性表(三) 1/.
第九章 查找表 9.1静态查找表 9.2动态查找表 9.3哈希表及其查找.
第九章 查找 2019/2/16.
第三章 栈和队列.
資料結構 第4章 堆疊.
数据结构 第八章 查找.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
王玲 第 2 章 线性表 王玲 2019/2/25.
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
7.1 广义表的概念 广义表是n(n≥0)个数据元素组成的序列,其中每个数据元素或是单个数据元素(简称原子),或仍然是一个广义表 。
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
第十章 结构体与链表 西安工程大学.
第6章 数组与广义表 6.1 数组的定义及其基本操作 6.2 数组的顺序存储结构 6.3 矩阵的压缩存储 6.4 广义表的概念
第六章 树和二叉树 学习要点 理解树的定义和基本术语,重点了解二叉树的定义、性质、存储结构; 掌握二叉树遍历的递归算法及它的典型运算;
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 字符串应用 5.4 字符串匹配算法 5.5 数组
第1章 绪论(二) 教学目标 理解算法的特性及评价标准 掌握算法时间复杂度和空间复杂度的分析方法 1/
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
演算法時間複雜度 (The Complexity of Algorithms)
第二章 线性表.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第 六 讲 栈和队列(一).
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
算法3.3 void InitList_sq(SqList &L,int msize=LIST_INIT_SIZE)
本节内容 1.二叉排序树的定义 2.二叉排序树的查找操作 3.二叉排序树的插入操作 4.二叉排序树的删除操作 5.二叉排序树的总结
Presentation transcript:

3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用 第三章 线性表 3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用

3.1 线性表及逻辑结构 线性表(Linear List):由n(n>0)个性质相同的数据元素组成的有限序列。线性表的长度即为线性表中元素的个数n(0),当n=0时,称该线性表为空表。 线性表举例: 英文字母表:(A, B, C,······, Z) 我国有34个省、市、自治区,组成一个线性表如下: (北京, 天津, 上海,······, 宁夏, 台湾)

线性表的有关概念 位序:在一个非空表 (a1 ,a2 ,…,ai,…,an-1 ,an) 中的每个数据元素都有一个确定的位置,如a1是第一个数据元素,an是最后一个数据元素,ai是第i个数据元素,称i为数据元素ai在线性表中的位序。 前驱/后继元素:若将线性表记为:(a1, ..., ai-1 , ai , ai+1 , ..., an ),则表中ai-1先于ai,ai先于ai+1,就称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。 注意: 除第一个元素a1元素以外,每一个数据元素有且仅有一个前趋元素, 除最后一个元素以外,每个数据元素有且仅有一 个后继元素。

有关线性表运算: 初始化InitList(L):创建一个空的线性表L。 计数ListLength(L):求线性表L的长度。 存取GetElem(L,i):存取第i个数据元素。 插入ListInsert(L,i):在第i个数据元素之前,插入一个新的数据元素;或在第i个元素后,插入一个新的数据元素。 删除ListDelete(L,i):删去第i个数据元素。 归并:把两个或两个以上的线性表合并在一起,形成一个新的线性表。

分拆:把一个线性表拆成两个或多个线性表。 查找:按某个特定的值查找线性表中的某个元素。 排序:对线性表中的某个元素按某个数据项的值递增(或递减)的顺序进行重新排序。

例 3-1 根据实例给出线性表归并的算法 已知线性表LA和LB中的数据元素按值非递减有序排列,现要求将LA和LB归并为一个新的线性表LC←LA∪LB,且LC中的数据元素仍按值非递减有序排列。设 LA=(1,5,7,15) LB=(3,6,8,9,13,15,17) 则 LC=(1,3,5,6,7,8,9,13,15,15,17)

算法思想: 设LC为空表 将LA或LB中的元素逐个插入到LC中即可 具体方法:为使LC中元素按值非递减有序排列,可设两个指针i和j分别指向LA和LB中某个元素,若设i当前所指的元素为a,j当前所指的元素为b,则当前应插入到LC中的元素c为

算法3.1 归并算法 Void MergeList(List *La, List *Lb, List *LC) { 算法3.1 归并算法 Void MergeList(List *La, List *Lb, List *LC) { InitList(Lc); /*构造一个空的线性表Lc*/ i=j=1;k=0; /*指针i和j初始值为1*/ La_len=ListLength(La); Lb_len=ListLength(Lb); while((i<=La_len)&&(j<=Lb_1en) { /* La和Lb均非空*/ GetElem(La,i,ai); GetElem(Lb,j,bj); if (ai <bj) Listlnsert(Lc,++k,ai); ++i; } /*将La中的元素插入到表Lc中*/

{ Listlnsert(Lc,++k,bj);++i;++j;} { Listlnsert(Lc,++k,bj);++j;} } else if (ai = bj ) { Listlnsert(Lc,++k,bj);++i;++j;} { Listlnsert(Lc,++k,bj);++j;} } While(i <=La_len) { /*如果表La没有取完,则将表La中的所剩元素插入到表lc中*/ GetElem(La,i++,ai); Listlnsert(Lc,++k,ai); While(j<=Lb_len) GetElem(Lb,j++,bj); Listlnsert(Lc,++k,bj); }/*MergeList*/ 算法3.1的时间复杂度是O(ListLength(La)+ListLength(Lb))

例3-2 利用线性表的基本运算来实现清除线性表LA中多余的重复结点,生成一个新的表LB。如有以下表,LA=(2,3,4,3,5,6,7,4,8,9)存在多余的重复结点,则LB=(2,3,4,5,6,7,8,9)

算法思想:从表LA的第一个结点i=1开始,逐个检查结点i以后的位置为k的任一元素,若两点相同,则从表LA中将位置k上数据元素删除掉,当遍历了i后面的所有元素后,i就成为表LA中无重复的结点,然后将i向后移动一个位置。重复上述过程,直到i移到表LA的最后一个元素为止

算法实现 : PURGE(LA)/*清除线性表中重复出现的多余结点*/ List *LA; { int i=1,k,x,y; int L=lenth(LA); while(i<L) x=get(LA,i);/*取当前第i个结点*/ k=i+1; while(k<=L) y=get(LA,k);/*取当前第k个结点*/

算法的时间复杂度:(n-1)+(n-2)+(n-3)+…..+1,即 if(x==y) { Delete(LA,k);/*删除*/ L--; } Else k++; i++; }/*PURGE*/ 算法的时间复杂度:(n-1)+(n-2)+(n-3)+…..+1,即

3.2 线性表的顺序存储 3.2.1 顺序存储 数据元素的存储位置: 3.2 线性表的顺序存储 3.2.1 顺序存储 线性表的顺序存储:把线性表的各个数据元素依次存储在一组地址连续的存储单元里 ;用这种方法存储的线性表简称为顺序表 数据元素的存储位置: (1) 第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间的关系: LOC(ai+1)=LOC(ai)+m (2) 线性表的第i个数据元素ai的存储位置为:LOC(ai)=LOC(a1)+(i-1)*m

顺序表的特点:表中相邻的元素ai 和ai+1 赋以相邻的存储位置

顺序表在C语言的一维数组表示 typedef int datatype;/*定义datatype类型为int*/ #define List_MaxSize 100 /*顺序表的最大长度*/ typedef struct{ datatype data[list_maxsize]; /*将线性表定义为一个数组*/ Int length; /*线性表当前的大小*/ }SqList;

3.2.2 顺序结构线性表的运算 表的初始化 求表长 void InitList(SqList *L) {\\顺序表的初始化即将表的长度设为0 L.Length=0; } 求表长 int ListLength(SqList *L) { \\求表长只需返回L.Length return L.Length;

取表中第i个结点 顺序表的结点查询操作 datatype GetNode(L,i) {\\取表中第i个结点只需返回L.data[i-1]即可 if (i<1||i> L.Length-1) Error("position error"); return L.data[i-1]; } 顺序表的结点查询操作 Int search( int x,sqlist *L,int n ) {/*在表长为n 的顺序表中查找结点x在表中的位置*/ int i; for(i=0;i<n;i++) if(x==L.s[i]) break; /*查询到跳出循环*/ return(i+1); /*返回查询结果*/ if(i==n) return(0);

顺序表的结点插入操作 :在线性表的第i-1个数据元素和第i个数据元素之间插入一个新的数据元素,就是要使长度为n的线性表 变成长度为n+1的线性表 例:

算法3.6 顺序表插入操作算法 Insert_Sq(SqList *L, int i,int e) { 算法3.6 顺序表插入操作算法 Insert_Sq(SqList *L, int i,int e) { if(i < 1 || i > L. Length) return ERR0R;/* i值不合法*/ if(L.length>list_maxsize-1) return error;/*当前存储空间已满,溢出*/ q = &(L.data[i-1]); /*q为插入位置*/ for(p=&(L.data[L.length-1];p>=q;--p) *(p+1)= *p; /*插入位置及之后的元素右移*/ *q=e; /*插入e*/ ++L.1ength; /*表长增1*/ return OK; } /*Insert_Sq*/ 算法时间复杂度是O(n)

顺序表的结点删除操作 删除操作:使长度为n的线性表(a1,…,ai-1 , ai, ,ai+1,…,an )变成长度为n-1的线性表(a1,…,ai-1 ,ai+1,…,an ) 图示:

算法: Delete_Sq(SqList *L,int i ,int &e) { if((i<1) || i>L.length)) return ERROR;/*i值不合法*/ p=&(L.data[i-1]); /*p为被删除元素的位置*/ e=*p; /*被删除元素的值赋给e*/ q=L.length-1; /*表尾元素的位置*/ for(++p; p <= q;++p) *(p-1)= *p; /*被删除元素之后的元素左移*/ --L.length; /*表长减1*/ return e; }/*Delete_Sq*/ 事件复杂度O(n)

3.2.3 顺序存储结构的特点 优点: 缺点: 无须为表示结点间的逻辑关系而增加额外的存储空间 可以方便地随机存取表中的任一结点 要占用连续的存储空间,并需要静态分配 在插入操作和删除操作时需要移动大量数据

3.3 线性表的链式存储 3.3.1 线性链表 线性表的链式存储结构:用一组任意的存储单元来存储线性表的数据元素 结点结构: 3.3 线性表的链式存储 3.3.1 线性链表 线性表的链式存储结构:用一组任意的存储单元来存储线性表的数据元素 结点结构: 数据域(Data Field):存储数据元素信息的域 指针域(Link Field):存放直接后继结点或前驱结点地址的域 图示:

单链表图示: 事例:

结点存储结构: 带头结点的单链表示意图 typedef struct Lnode {/*线性表的单链表存储结构*/ Datatype data; Struct Lnode * next; }LinkList; 带头结点的单链表示意图

带头结点单链表初始化算法 建立单链表的算法 Initlist(LinkList *L) { L = (LinkList*)malloc(sizeof(LNode)); L->next = NULL; } 建立单链表的算法 Create_L(LinkList *L,int n) LinkList*p;int i; initlist(LinkList *L)/*建立一个带头结点的单链表*/ for(i = n;i>0;--i) p = (LinkList*)malloc(sizeof(LNode)); /*生成新结点*/ scanf(&p->data); /*输入元素值*/ p->next =L->next; L->next = p; /*插入到表头*/ } }/* Create_L */

单链表的查找操作 单链表的插入操作 单链表的删除操作 3.3.2 线性链表的运算 单链表的查找操作 单链表的插入操作 单链表的删除操作

单链表的查找操作 单链表的查找操作算法 VisitElem_L(LinkList *L, int i, Datatype &e ) { LinkList *p,int j; p = L->next;j=1; While(p!=null &&j<i ) {/*顺指针向后查找,直到p指向第i个元素或p为空*/ p=p->next; ++j; } if(p=null || j>i ) return ERROR; /*第i个元素不存在 */ e=p->data; /*取第i个元素*/ return OK; }/*VisitGetElem_L*/

ListNode* LocateNode (LinkList head,DataType key) 按值查找链表 ListNode* LocateNode (LinkList head,DataType key) { ListNode *p=head->next; while(p&&p->data!=key)//直到p为NULL或p->data为key为止 p=p->next; return p; }

插入位置: 将结点插入在链表的第一个结点位置 将结点插入在两个结点之间 将结点插入在链表的最后一个结点 插入前后指针变化 单链表的插入操作 插入位置: 将结点插入在链表的第一个结点位置 将结点插入在两个结点之间 将结点插入在链表的最后一个结点 插入前后指针变化

单链表的结点前插算法 Insert_Link(LinkList *L,int i, Datatype e) { LinkList*p,*s; int j; s = (LinkList*)malloc(sizeof(LNode)); /*生成新结点*/ s->data = e; s->next =null; p = L ; j = 0; While(p && j < i-1) p = p->next; ++j; } /*寻找第i-1个结点*/ if(!p||j>i-1) return ERROR; /*i小于1或者大于表长*/ s->next = p->next; p->next = s; return OK; }/*Insert_Link*/

单链表的结点后插算法 Insert_Link(LinkList *L,int i, Datatype e) { LinkList*p,*s; int j; p = L ; j = 0; s = (LinkList*)malloc(sizeof(LNode)); /*生成新结点*/ s->data = e; s->next =null; While(p && j < i) p = p->next; ++j; } /*寻找第i-1个结点*/ if(!p||j>i) return ERROR; /*i小于1或者大于表长*/ s->next = p->next; /*插入L中*/ p->next = s; return OK; }/*Insert_Linnk*/

单链表的删除操作 删除前后指针变化:

单链表删除算法 Delete_Link(LinkList *L,int i,Datatype &e) { Linklist*p,*q; int j; p = L; j = 0; while(p->next && j<i-1) {/*寻找第i个结点,并令p指向其前趋*/ p = p->next; ++j; } if(!(p->next)||j>i-1) return ERROR; /*删除位置不合理*/ q = p->next; p->next = q->next; /*删除结点*/ e = q->data; free(q); /*释放结点*/ return OK; }/*Delete_Link*/

例题:逆序带头结点的单链表 ,使表(a1,…,ai-1 , ai, ,ai+1,…,an )转换成为(an,…,ai+1 , ai, ,ai-1,…,a1) 算法: void InvertLink(LinkList *Head) { LinkList *P; P = Head->Next; /*P指向原表中第一个待逆置的结点*/ Head->Next = NULL; /*逆表Head初值为空表*/ while (P != NULL) /* 原表中还有未逆置的结点*P */ S = P; P = P->Next; S->Next = Head->Next; Head->Next = S /*将*S 插到逆表Head的头上*/ } } /*InvertLink*/

3.3.3 静态链表 实现方法:一维数组 结构 #define StaticTableSize 100 事例: typedef Struct Slink { Datatype data; Int next; }SlinkTable[StaticTableSize]; 事例:

3.3.4 静态链表的运算 静态链表删除操作: DeleteSlinkElement(Slink S,int n) { 3.3.4 静态链表的运算 静态链表删除操作: DeleteSlinkElement(Slink S,int n) { i=S[0].next; //取得静态链表的第一个元素的地址 for (Count=0;Count<=n,Count++) { Pre=i; i=S[i].next;}//在表中查找第n个元素的位置 S[Pre].next=S[i].next; //删除该元素 }

静态链表的查找操作 int SearchSL(Slink S,datatype Value) { i=S[0].next; while (i && S[i].data!=Value) i=S[i].next; return i; }

循环链表 :使其最后一个结点的指针指向链表的第一个结点,使链表呈环状,这种形式的线性表叫做循环链表 图示: 3.3.5 循环链表 循环链表 :使其最后一个结点的指针指向链表的第一个结点,使链表呈环状,这种形式的线性表叫做循环链表 图示:

结点结构描述: struct Cnode { Int data; struct Cnode *next; }Clinklist;

3.3.6 循环链表的运算 循环链表中查找元素为e的结点 VisitElem_L(CLinklist *L, Datatype e ) { 3.3.6 循环链表的运算 循环链表中查找元素为e的结点 VisitElem_L(CLinklist *L, Datatype e ) { Clinklist*p; p = L->next; /*初始化,P指向第一个结点*/ While(p->next!=L &&p->data!=e) p=p->next; if(p->next=L &&p->data!=e) return ERROR; /*元素e不存在 */ Return (p); }/*VisitGetElem_L*/

循环链表的合并操作 图示:

两个循环链表的链接算法 CLinkList *Connect(CLinklist *rearA,CLinklist *rearB) { CLinklist *p; p=rearA->next; rearA ->next=rearB->next->next; /*rearB表的第一个结点接在reaA的表尾*/ free(rearB->next); rearB->next=p;/*将链表rearB的第一个结点链接到rearA的最后一个结点之后*/ return rearB;/*返回连接后的循环链表尾指针*/ }/*Connect*/

双向链表:每一个结点有两个指针域,一个指针指向其直接前驱结点,另一个指针指向直接后继结点 图示: 3.3.7 双向链表 双向链表:每一个结点有两个指针域,一个指针指向其直接前驱结点,另一个指针指向直接后继结点 图示:

结点结构描述 循环双向链表 typedef struct DuLNode {/*线性表的双向链表存储结构*/ DataType data; Struct DuLNode *priou;/*指向前一结点的指针*/ Struct DuLNode *next; /*指向后一结点的指针*/ }DuLinkList; 循环双向链表

3.3.8 双向链表的运算 双向链表的结点删除操作 : 指针变化: 3.3.8 双向链表的运算 双向链表的结点删除操作 : 指针变化: 指针变化:(p-> priou)->next=p->next; (p-> next)-> priou= p-> priou;

算法: Delete_DuL(DuLinkList *L,int i,Datatype &e) { e = p->data; p-> priou ->next = p->next; p->next-> priou = p-> priou; /*删除结点*/ free(p); /*释放空间*/ return e; }/*Delete_DuL*/

双向链表的结点插入操作 图示:

算法: Insert_DuL(DuLinkList *L,int i,datatype e) { if(!(s=(DuLlinkList)malloc(sizeof(DuLNode)))) return ERROR; s->data = e; s->next = p->next; p-> next -> priou = s; s->priou = p; p->next = s; return OK; }/*Insert_DuL*/

3.3.9 链式存储结构的特点 优点: 缺点: (1)结点空间的动态申请和动态释放,克服了顺序存储结构数据元素最大个数需要预先设定的缺点 3.3.9 链式存储结构的特点 优点: (1)结点空间的动态申请和动态释放,克服了顺序存储结构数据元素最大个数需要预先设定的缺点 (2)链式存储结构中数据元素之间的次序是使用指针来控制的,在插入删除时需要移动大量的数据 缺点: (1)每个结点的指针域需要另外加存储空间 (2)链式存储是一种非随机存储结构,对于任意结点的操作都要首先从开始指针顺链查找该结点,增加了一些操作的算法时间复杂度

3.4 链式存储结构的应用 3.4.1 约瑟夫问题 问题描述:设有n个人坐在圆桌周围,从第s个人开始报数,数到m的人出列,然后再从下一个人开始报数,数到m的人又出列,……,如此重复,直到所有的人都出列为止。要求按出列的先后顺序输出每个人的信息 算法: typedef struct Lnode { Datatype data; Struct Lnode * next; }LinkList;

void Joseph(int n,int s,int m) {/*约瑟夫问题*/ int I,j; LinkList *creatlinklist(int); LinkList *h,* p,*q, *m, *r; if (n<s) return error; h= creatlinklist(int);/*建立一个带头结点的单链表*/ q=h; for(I=1;I<s;I++)q=q->next;/*找出s结点*/ p=q->next; for(I=1;I<n;I++) { for(j=1;j<m;j++) /*报数,找出数m的结点*/ if(q->next!=null)&& (p->next!=null) q=q->next; p=p->next; }

else if (p->next= =null) { q=q->next; p=h->next; } else q=h->next; p=p->next; printf(“%c\n”,p->data);/*一个元素出列*/ r=p; if (p->next= =null) p=h->next; q->next=null; p=p->next; if (q->next!=null) q->next=p; else h->next=p; free(r); printf(“%c\n”,(h->next)->data);

3.4.2一元多项式求和 多项式:Pn (x) = p0 + p1 xe1+ p2 xe2 + ...+ pn xen 在计算机中的表示 其中,pi(i=1,2,3,n)是系数;ei是相应的指数,且有en>en-1>>e1  0 在计算机中的表示

事例:P=13x40+6x30+2x15+4x3+15 Q=10x35-6x30-4x8 运算步骤: 若两项的指数相等,则系数相加 若两项的指数不等,则分别将两项加在结果中

运算规则:假设指针qa和qb分别指向多项式A和多项式B中当前进行比较的某个结点,la和lb分别指向qa和qb的前一个结点 (1)指针qa所指结点的指数值 > 指针qb所指结点的指数值,则应取qa指针所指结点插入到“和多项式”链表中去,qa的指针后移 (2)指针qa所指结点的指数值 < 指针qb所指结点的指数值,则应取指针qb所指结点插入到“和多项式”链表中去,qb指针后移 (3)指针qa所指结点的指数值 = 指针qb所指结点的指数值,则将两个结点中的系数相加,若和数不为零,则修改qa所指结点的系数值,同时释放qb所指结点;反之,从多项式A的链表中删除相应结点,并释放指针qa和qb所指结点

事例: 结果:

算法: typedef struct poly { float coef; /*系数*/ int expn; /*指数*/ struct poly *next; /*指针*/ }polynode/**/ Polynode CreatPoly ( polynode *P,int m) po1ynode *r; InitList(P);/*初始化线性链表P*/ h=GetHead(P);/*得到头结点*/ h.coef = 0.0; /*设置头结点的数据元素*/ h.expn = -1; r=p;

for(i=1; i<=m; ++i ) { /*依次输入m个非零项*/ scanf(e.coef,e.expn); if(LocateElem(p,e)=null) { /*当前链表中不存在该指数项*/ p-> coef =e.coef; p-> expn=e.expn; r->next=p;/*生成结点并插入链表*/ } r->next=p; return(P); }/*CreatPo1yn*/

Ploynode AddPoly(polynode *Pa, polynode *Pb) { /*ha和hb分别指向Pa和Pb的头结点*/ ha = GetHead(Pa); la=ha; hb = GetHead(Pb); lb=lb; /*qa和qb分别指向Pa和Pb中当前结点*/ qa = la->Next; qb = lb->Next; while(pa!=null&& pb!=null) { /*Pa和Pb均非空,指数比较*/ if (qa->expn > qb->expn) /*多项式Pa中当前结点的指数值小*/ la = qa; qa = qa->Next; }

if (qa->expn = qb->expn) /*两者的指数值相等*/ { sum = qa->coef + qb->coef; if(sum !=0.0)) { /*修改多项式Pa中当前结点的系数值*/ qa->coef=sum; la = qa; } else /*系数为0*/ { /*删除多项式Pa中当前结点*/ la->next=qa->next; Free(qa); /*释放空间*/ qa = qa->next; lb->next=qb->next; Free(qb); /*释放空间*/ qb = qb ->Next; }

if (qa->expn < qb->expn) {/*多项式Pb中当前结点的指数值小*/ lb->next=qb->next; la->Next= qb; qb->next=qa; la=qb; qb=lb->next; } }/*while*/ if(Pb!=null)la->next=qb; /*链接Pb中剩余结点*/ Free(lb); /*释放Pb的头结点*/ Return(Pa); }/*addpoly*/

3.4.3 在集合方面的应用 应用事例:从终端输入两组数据,分别表示两个集合的元素A和B,要求算出(A-B)U(B-A) 算法: 3.4.3 在集合方面的应用 应用事例:从终端输入两组数据,分别表示两个集合的元素A和B,要求算出(A-B)U(B-A) 算法: int createlink(Slink t) { int head,p,q,item; scanf(“%d”,&item); //输入元素值 p=malloc(s); //用head保留新建链表的链头指针 head=p; s[p].data=item;q=p; while(true) scanf(“%d”,&item); //输入节点值 if (!item) break; //输零结束

p=malloc(s); s[p].data=item; s[q].next=p; q=p; } s[q].next=0; reture head; 计算(A-B)U(B-A) int differ(Slink s) { int a,b,p,q,r,tail1,tail2; init(s); //初始化存储栈 a=creatlink(s); //静态链表A建立 b=creatlink(s); //静态链表B建立 p=a;

while(s[p].next!=0) p=s[p].next; //遍历A,找tail1 tail1=tail2=p; while(b) { r=b; b=s[b].next; //b为链表b中的后续节点地址 p=a; while(p!=s[tail1].next && s[p].data!=s[r].data) { q=p; p=s[p].next; } if (p==s[tail1].next) s[tail2].next=r; tail2=r; else

{ if (p= =a) q=a; a=s[a].next; free(s,q); }//释放重复节点所占的空间 else s[q].next=s[p].next ; free(s,p); } free (s,r); s(tail2).next=0; //表尾后续指针置0 return a;