1 / 30

第 14 章 线性表

第 14 章 线性表. 本章目标 介绍线性表的概念及其存储结构的 C++ 定义: 顺序表 和 链表 学习要求 掌握线性表的顺序存储结构 C++ 定义 ---- 即顺序表类的定义 掌握顺序表的 插入函数 和 删除函数 掌握线性表的非顺序存储结构 C++ 定义 ---- 即单链表类的定义 掌握单链表的 插入函数 和 删除函数. 什么是线性表. 日常生活中常见到表格形式的一类数据 列车时刻表 学生成绩表 周名缩写表. 车次. 火车种类. 始发站. 终点站. 始发时间. 到达时间. 140. 特快. 西安. 上海. 20 : 30. 19 : 45.

Download Presentation

第 14 章 线性表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第14章线性表 本章目标 介绍线性表的概念及其存储结构的C++定义:顺序表和链表 学习要求 掌握线性表的顺序存储结构C++定义----即顺序表类的定义 掌握顺序表的插入函数和删除函数 掌握线性表的非顺序存储结构C++定义----即单链表类的定义 掌握单链表的插入函数和删除函数

  2. 什么是线性表 日常生活中常见到表格形式的一类数据 列车时刻表 学生成绩表 周名缩写表

  3. 车次 火车种类 始发站 终点站 始发时间 到达时间 140 特快 西安 上海 20:30 19:45 42 特快 西安 北京 17:30 7:45 361 普快 西安 铜川 9:45 13:10 …… …… …… …… …… …… 列车时刻表

  4. 学号 姓名 性别 分数 99011001 周敏 女 86 99011002 苏伊诗 女 92 99011003 王苏朋 男 76 …… …… …… …… 学生成绩表

  5. Sun. Mon. Tue. Wen. Thu. Fri. Sat. 周名缩写表

  6. 上述表格形式的数据具有如下共同特点: 1)表中每一行信息虽然组成的内容不同,但都代表某个明确独立的含义,将表中每一行信息称之为一个数据元素; 2)每个数据元素在表中的位置固定,除了第一个元素和最后一个元素外,其余元素都有唯一一个前驱元素和唯一一个后继元素; 3)表中数据元素的个数不相同,有长有短; 4)大多数表中数据元素会增加或减少,是动态变化的。但也有一些表是固定不变, 将这些表格形式的数据加以抽象,统称为线性表。

  7. 线性表的定义 线性表是由n(n≥0)个数据元素a 1,a 2,a 3,…,a n组成的有限序列,记为:(a 1,a 2,a 3,…,a n)。 线性表中当前存储的数据元素数目叫做表的长度,n为表长,当线性表中不包含任何数据元素时,称为空表。显然n=0时称为空表。 1)数据元素a i(1≤i≤n)表示某个具体意义的信息,它可以是一个数,或者是一个字符串,或者是由数和字符串组成的更复杂的信息。但同一个线性表中的所有数据元素必须具有相同的属性(或者说具有相同的数据类型); 2)若线性表是非空表,则有:(ⅰ)第一个元素a 1无前趋元素;(ⅱ)最后一个元素a n无后继元素;(ⅲ)其它元素a i(1<i<n)均只有一个直接前趋a i-1和一个直接后继a i+1。

  8. 日常生活中线性表的例子 某校1998—2003年在校学生人数(2500,3450,5000,5100,5400,5500)是一个线性表,每个数据元素是一个正整数,表长为6; 每个月份英文缩写名称组成一个线性表(JAN.,FEB.,MAR.,APR.,MAY.,JUN.,JUL.,AUG.,SEP.,OCT.,NOV.,DEC.),表中数据元素是一字符串,表长为12; 屏幕上若干像素((50,50,RED),(100,150,RED),(200,200,BLUE),(200,250,GREEN))亦是一线性表,表中数据元素是由行坐标、列坐标和颜色三个数据项组成的一个像素信息,表长为4。 电话号码簿、股票市场里的信息列表、航班时刻表、各种各样的统计报表等等

  9. 对线性表有哪些处理(或操作)呢? 基本的、常用的处理如下: 1)统计线性表里总共有多少个元素。简称求表长,记作Length(L), 2)获取线性表中某个数据元素的信息。简称取元素,记作Get(L,i) 3)置换或修改线性表中某个数据元素的信息。简称置换元素,记作Replace(L,i,x) 4)在线性表中某个位置上增加一个数据元素。简称插入元素,记作Insert(L,i,x) 5)删除线性表中某个位置上的一个数据元素。简称删除元素,记作Delete(L,i) 6)查找某个数据元素是否在线性表中存在。简称查找元素,记作Locate(L,x) 7)求前驱元素,记作Prior(L,i),取元素ai的直接前驱 8)求后继元素,记作Succ(L,i) 9)对线性表中的数据元素按某个数据项的值递增(或递减)的顺序排列。简称排序,记作Sort(L)。

  10. 顺序表类

  11. 顺序表类的定义(1) • #include <iostream.h> • template <class datatype> • class seqlist • { private: • datatype *data; • int maxsize; //maxsize为线性表的最大可能长度 • int last; //last为线性表中表尾元素的下标 • public: • seqlist() //创建100个元素的线性表的构造函数 • { maxsize=100; • data=new datatype[maxsize]; • last=-1; //last为-1表示为空表 • } • seqlist(int sz) //创建sz个元素的线性表的构造函数 • { if(sz>0) • maxsize=sz; • else • maxsize=100; • data=new datatype[maxsize]; • last= -1; //last为 -1表示为空表 • } • bool isempty(){ return last==-1?true:false; } //判空表 • bool isfull(){ return last==maxsize-1; } //判表满 • int length(){ return last+1; } //求表长

  12. 顺序表类的定义(2) • bool getdata(int i,datatype &x) //取元素 • { i--; • if (i>=0&&i<=last) • { x = data[i]; • return true; • } • else • { cout<<”非法位置读取元素,不能读取!\n”; • return false; • } • } • bool get_prior(int i,datatype &x); //取前驱元素 • bool get_succ(int i,datatype &x); //取后继元素 • bool replace(int i,datatype x) //置换元素 • { i--; • if (i>=0&&i<=last) • { data[i]=x; • return true; • } • else • { cout<<”非法位置修改元素,不能修改!\n”; • return false; • } • } • bool insert_data(int i,datatype x); //插入元素 • bool delete_data(int i); //删除元素 • void print_list(); //显示表中所有元素 • int find_data(datatype x); //查找元素 • void sort(); //排序元素 • ~seqlist(){ delete[] data; } //析构函数 };

  13. 顺序表类定义的说明 • maxsize为线性表中数据元素个数最大可能值 • last为线性表中当前实际存入的最后一个数据元素下标 • 构造函数有两个重载形式seqlist()和seqlist(int sz)。 • 构造函数创建了datatype类型的一维数组,数据元素在数组里按次序紧密存放 • 析构函数~seqlist()将申请的存储空间释放,data指针指向该空间的首地址 • 数据元素的类型定义为模板是为了定义一个通用类型的线性表

  14. 学生成绩单的定义 struct student_score_table { long num; char name[9]; char sex; float score; }

  15. 声明几个顺序表类的对象 • seqlist <int> la(2000); • seqlist <string> lb(2000); • seqlist <struct student_score_table> lc(2000); 以上顺序表类中,还有插入、删除、查找、排序四个函数没有定义函数体,下面讨论插入和删除两个函数的算法实现,查找和排序函数的算法实现放在下一章讨论。

  16. template<class datatype> bool seqlist<datatype>:: insert_data(int i, datatype x) { if ( isfull() ) // 判定表满否 { cout<<”表已满,不能插入!\n”; return false; } if ( i>=1 && i<=last+2 ) // 判定插入位置i的合法性 { // 第n至第i个元素循环后移一个存储位置 for (int j=last;j>=i-1;j--) data[j+1]=data[j]; data[j+1] =x; // x成为线性表中第i个元素 last++; // 线性表的长度加1 return true; } else { cout<<"插入位置错误,不能插入!\n"; return false; } } 插入算法的主要步骤和C函数如下: 插入前:(a 1,a 2,…,a i-1,a i,…,a n) 插入后:(a 1,a 2,…,a i-1,x ,a i,…,a n) 第1步: 判定表不满方可插入; 第2步: 判定插入位置i的合法性; 第3步: 将第n至第i个元素后移一个存储位置; 第4步: 将x插入到a i-1之后; 第5步: 线性表的长度加1。

  17. template<class datatype> bool eqlist<datatype>:: delete_data(int i) { if( isempty() ) // 判定表空否 { cout<<”表已空,不能删除!\n”; return false; } if ((i>=1)&&(i<=last+1)) // 判定删除位置i的合法性 { // 第i+1至第n个元素循环前移一个存储位置 for (int j=i-1;j<last;j++) data[j]=data[j+1]; last--; // 线性表的长度减1 return true; } else { cout<<”删除位置错误,不能删除!\n”; return false; } } 删除算法的主要步骤和C++函数如下: 删除前:(a 1,a 2,…,a i-1,a i,a i+1,…,a n) 删除后:(a 1,a 2,…,a i-1,a i+1,…,a n) 第1步:判定表不空方可删除; 第2步:判定删除位置i值的合法性; 第3步:将第i+1至第n个元素依次向前移动一个存储位置; 第4步:将线性表的长度减1。

  18. 综合分析线性表的顺序存储结构有五个特点 1)可以随机存取线性表中每一个元素,存取元素的速度与它在表中的位置无关; 2)不需要额外开辟空间存储关系集合,其逻辑关系隐含在物理存储结构中; 3)插入和删除元素速度较慢,平均地讲每插入或删除一个元素需要移动表长的一半元素; 4)扩充性差,注意顺序表类定义中MAXSIZE值的确定是件困难的事,MAXSIZE值太大造成存储空间冗余,太小不利于扩充; 5)需要一整块连续空间,但表中元素进进出出,不可能一下子放满,有存储空间空闲不能作为它用。

  19. 线性表的非顺序存储结构----链表类 设计新的存储结构,改进顺序表的结构: 1、线性表中有多少元素就开辟多少存储空间,不预留空间; 2、元素之间不需要紧挨着存放,元素可以散落在存储器中任何地方; 3、插入和删除都不需要移动大量元素;

  20. data next 每个元素的存储结构 template<class datatype> class NODE { public: datatype data; //数据域 NODE<datatype> *next; //指针域 };

  21. 线性表的非顺序存储结构图 指针将线性表中每一个元素有机地连接在一起,指针像链条一样,所以线性表的非顺序存储结构又称链式结构 有了结点类的定义,就可以将整个线性表定义成如下单链表类:

  22. 单链表类(1) • template<class datatype> • class LIST • { private: • NODE<datatype> *head; • public: • LIST(){ head=NULL; } //构造函数 • int length(); //求表长 • bool get_data(int i,datatype &x); //取元素 • bool get_succ(int i,datatype &x); //取前驱元素 • bool get_proc(int i,datatype &x); //取后继元素 • bool replace_data(int i,datatype x); //置换元素 • NODE<datatype> *find_data(int i); //查找元素 • void sort(); //排序 • bool insert_data(datatype data,int i); //插入元素

  23. 单链表类(2) • bool delete_data(int i); //删除元素 • void print_list(); //打印所有元素 • bool insert_rear(datatype data); //从表尾插入元素 • bool insert_head(datatype data); //从表头插入元素 • ~LIST() //析构函数 • { • NODE<datatype> *p; • while(head) //将链表中所有元素占用空间释放 • { • p = head; • head = head->next; • delete p; • } • } • };

  24. 单链表类的特点 1)线性表中实际有多少元素就存储多少个结点 2)元素存放可以不连续,其物理存放次序与逻辑次序不一定一致,换句话说,a i-1可能存放在存储器的下半区,而a i可能存放在存储器的上半区 3)线性表中元素的逻辑次序通过每个结点指针有机地连接来体现 4)插入和删除不需要大量移动表中元素。

  25. Newnode = new NODE<datatype>; newnode->data=data; newnode->next=current; previous->next=newnode;

  26. template<class datatype> bool LIST<datatype>:: insert_data(float data,int i) { NODE<datatype> *current,*previous,*newnode; int j=1; if((i>length()+1)||(i<0)) //判定插入位置正确与否 { cout<<"插入位置不正确,不能插入!\n"; return false; } newnode=(NODE *)malloc(sizeof(NODE)); //申请新结点空间 if(newnode==NULL) { cout<<"内存无空间,表已满,不能插入!\n"; return false; } newnode->data=data; newnode->next=NULL; if(i==1) //插入表头,另做处理 { newnode->next=head; head=newnode; return true; } current=previous=head; while(current!=NULL&&j<i) //寻找插入位置 { previous=current; current=current->next; j++; }; newnode->next=current; //修改新结点的指针域 previous->next=newnode; //修改ai-1结点的指针域 return true; }

  27. previous->next=current->next; delete current;

  28. template<class datatype> bool LIST<datatype>:: delete_data(int i) { NODE<datatype> *current,*previous; int j=1; if(head==NULL) //判定是否为空表 { cout<<"表已空,不能删除。\n"; return false; }; if((i<1)||(i>length())) //判定删除位置是否正确 { cout<<"删除位置不正确,不能删除!\n"; return false; } current=previous=head; while(current&&j<i) //寻找删除位置 { previous=current; current=current->next; j++; }; if(head==current) //删除表头元素另做处理 { head=head->next; delete current; } else { previous->next=current->next; //修改ai-1结点指针域 delete current; //释放被删结点的存储空间 } return true; }

  29. 作业 作业1:编写测试主函数,测试顺序表的插入和删除函数的正确性 作业2:编写测试主函数,测试单链表的插入和删除函数的正确性 作业3:本章习题1 作业4:本章习题2 作业1和作业2提示:粘贴插入和删除函数 编写打印线性表函数 再粘贴测试主函数

More Related