第2章线性表Word文件下载.docx
- 文档编号:20358295
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:37
- 大小:189.25KB
第2章线性表Word文件下载.docx
《第2章线性表Word文件下载.docx》由会员分享,可在线阅读,更多相关《第2章线性表Word文件下载.docx(37页珍藏版)》请在冰豆网上搜索。
访问。
对线性表中指定位置的数据元素进行取值或置值操作。
●Count:
求长度。
求线性表的数据元素个数。
●Insert:
插入。
在线性表指定位置上,插入一个新的数据元素,插入后仍为一个线性表。
●Remove:
删除。
删除线性表指定位置的数据元素,同时保证更改后的线性表仍然具有线性表的连续性。
●Copy:
复制。
重新复制一个线性表。
●Join:
合并。
将两个或两个以上的线性表合并起来,形成一个新的线性表。
●Search:
查找。
在线性表中查找满足某种条件的数据元素。
●Sort:
排序。
对线性表中的数据元素按关键字的值,以递增或递减的次序进行排列。
●Traversal:
遍历。
按次序访问线性表中的所有数据元素,并且每个数据元素恰好访问一次。
2.1.2C#中的线性表类
1.非泛型线性表类ArrayList
.NETFramework的类库中定义了一个线性表类ArrayList,它定义在System.Collections命名空间中。
ArrayList类提供了一种使用大小可按需动态增加的数组,其数据元素的类型是object类。
插入线性表的数据元素是object对象,所以可以是任意类型对象;
获取线性表某元素的数据可用object对象保存,一般需根据要求转化为string或其他类型的对象。
ArrayList类具有如下成员(属性和方法)实现线性表的各种操作:
公共构造函数
ArrayList();
//初始化ArrayList类的新实例
ArrayList(ICollectionc);
//初始化ArrayList类的新实例,它包含从指定集合复制的元素并且具有与所复制的元素数相同的初始容量。
ArrayList(intcapacity);
//初始化ArrayList类的新实例,它具有指定的初始容量。
公共属性
virtualintCount{get;
}//返回线性表的长度,即包含的元素数
virtualintCapacity{get;
set;
}//获取或设置线性表可包含的元素数
virtualobjectthis[intindex]{get;
}//获取或设置指定索引处的元素
公共方法
virtualvoidInsert(intindex,objectvalue);
//将数据元素插入指定位置
virtualintAdd(objectvalue);
//将对象添加到表的结尾处
virtualvoidAddRange(ICollectionc);
//将集合对象添加到表的结尾处
virtualintIndexOf(objectvalue);
//返回给定数据首次出现位置
virtualboolContains(objectitem);
//确定某个元素是否在表中
virtualvoidRemove(objectobj);
//从表中移除特定对象的第一个匹配项
virtualvoidRemoveAt(intindex);
//删除指定位置的数据元素
virtualvoidReverse();
//将表中元素的顺序反转
virtualvoidSort();
//对表中元素进行排序
2.泛型线性表类List<
T>
2.0版C#语言和公共语言运行库(CLR)中增加了泛型(Generics)。
泛型通常与集合一起使用。
.NETFramework2.0版类库提供一个新的命名空间System.Collections.Generic,它包含定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供比非泛型集合更好的类型安全性和性能。
建议面向2.0版的所有应用程序都使用新的泛型集合类,如List<
,而不要使用旧的非泛型集合类,如ArrayList。
List<
类是ArrayList类的泛型等效类,表示可通过索引访问的对象的强类型列表,它定义在System.Collections.Generic命名空间中。
泛型类List<
在大多数情况下比非泛型类ArrayList执行得更好并且是类型安全的。
类所具有的属性和方法非常类似于ArrayList类对应的属性和方法,差别在于前者是强类型列表,元素的类型要与列表定义时声明的类型保持一致。
List<
();
//初始化List<
类的新实例
(IEnumerable<
c);
//初始化List<
类的新实例,它包含从指定集合复制的元素并且具有与所复制的元素数相同的初始容量。
virtualTthis[intindex]{get;
}//获取或设置指定索引处的元素
virtualvoidInsert(intindex,Tvalue);
//将数据元素插入指定位置
virtualvoidAdd(Tvalue);
virtualvoidAddRange(IEnumerable<
//将集合对象添加到表的结尾处
virtualintIndexOf(Tvalue);
//返回给定数据首次出现位置
virtualboolContains(Titem);
virtualvoidRemove(Titem);
//从表中移除特定对象的第一个匹配项
下面是几个声明并构造特定类型列表的例子:
int>
a=newList<
();
//声明并构造整型数列表
a.Add(86);
a.Add(100);
//向列表中添加整型元素
string>
s=newList<
//声明并构造字符串列表
s.Add(“Hello”);
s.Add(“C#2.0”);
//向列表中添加字符串型元素
Student>
st=newList<
//声明并构造学生列表
st.Add(newStudent(“200518001”,“王兵”));
//向列表中添加学生类型元素
3.0版C#语言增加了“集合初始化器”来方便集合对象的初始化,例如:
num=newList<
{0,1,2,6,7,8,9};
集合初始化器其实是利用编译时技术对初始化器中的元素进行按序调用Add(T)方法。
【例2.1】创建并初始化ArrayList以及打印出其值。
publicclassSamplesArrayList{
publicstaticvoidMain(){
//CreatesandinitializesanewArrayList.
ArrayListmyAL=newArrayList();
myAL.Add("
Hello"
);
World"
myAL.Add("
!
"
//DisplaysthepropertiesandvaluesoftheArrayList.
Console.WriteLine("
myAL"
\tCount:
{0}"
myAL.Count);
Console.Write("
\tValues:
foreach(objectoinmyAL){
\t{0}"
o);
}
Console.WriteLine();
myAL.Sort();
\tSortedValues:
for(inti=0;
i<
myAL.Count;
i++){
myAL[i]);
程序运行结果如下:
myAL
Count:
3
Values:
HelloWorld!
SortedValues:
!
HelloWorld
【例2.2】以顺序表求解约瑟夫环问题。
约瑟夫环(Josephus)问题:
古代某法官要判决n个犯人的死刑,他使用了一条荒唐的方法,让犯人站成一个圆圈,从第s个人开始数起,每数到第d个犯人,就拉出来处决,然后再数d个,数到的人再处决……直到剩下的最后一个人可以得到赦免。
解决这个问题的直接思路是:
用有n个元素的线性表分别表示n个人,利用取模运算实现环形计数,当某人该出环时,删除表中相应位置的数据元素。
实现这种直接思路的程序为:
usingSystem;
usingSystem.Collections;
publicclassJosephus{
publicstaticvoidMain(string[]args){
JosephusStart(5,1,2);
}
publicstaticvoidShow(ArrayListalist){
foreach(objectoinalist){
Console.Write(o+"
"
}
Console.WriteLine();
publicstaticvoidJosephusStart(intn,ints,intd){
//n为总人数,从第s个人开始数起,每次数到d。
ArrayListaRing=newArrayList();
//List<
aRing=newList<
()
inti,j,k;
for(i=1;
i<
=n;
i++)aRing.Add(i);
//n个人依次插入线性表
Show(aRing);
i=s-2;
//第s个人的下标为s-1,i初始指向第s个人的前一位置
k=n;
//每轮的当前人数
while(k>
1){//n-1个人依次出环
j=0;
while(j<
d){
j++;
//计数
i=(i+1)%k;
//取模运算实现环形计数
}
Console.WriteLine("
out:
+aRing[i]);
aRing.RemoveAt(i);
//第i个人出环,删除第i个位置的元素
k--;
i=(i-1)%k;
Show(aRing);
Console.WriteLine("
\n{0}isthelastperson"
aRing[0]);
}
12345
2
1345
4
135
1
35
5
3
3isthelastperson
2.2线性表的顺序存储结构
用顺序存储结构实现的线性表称为顺序表。
线性表的顺序存储结构是用一组连续的存储单元顺序存放线性表的数据元素,数据元素在内存的物理存储次序与它们在线性表中的逻辑次序是一致的,即数据元素ai与其前驱数据元素ai-1及后继数据元素ai+1的位置相邻。
线性表中的数据元素属于同一种类型,因此每个数据元素在内存中占用的空间大小是相同的。
假设每个数据元素占据c个存储单元,第一个数据元素的地址为Loc(a0),则第i个数据元素的地址为:
Loc(ai)=Loc(a0)+i×
c,i=0,1,2,...,n-1
可见,每个数据元素的地址是该元素在线性表中位置(下标)的线性函数,该地址可以直接由下标计算出来,而且每次地址计算所花费的时间都是相同的。
因此,在顺序存储结构的线性表中,每个数据元素是可以随机访问的。
顺序表的存储结构如图2.1所示。
图2.1线性表的顺序存储结构
2.2.1顺序表的类定义
用C#程序设计语言中的数组可以作为实现顺序表的基础。
下面声明的SequencedList<
类表示顺序表,其中一维数组items是数据元素所占用的存储空间,元素类型为T,即与泛型顺序表的类型参数T相同的类型,count表示顺序表的长度,capacity表示顺序表的当前容量。
类声明如下:
publicclassSequencedList<
{
privateT[]items;
privateintcount=0;
privateintcapacity=0;
……
线性表的操作将作为SequencedList类的属性和方法成员予以实现。
SequencedList类的一个实例表示一个线性表。
当我们需要使用一个线性表时,就创建SequencedList类的一个对象,通过对这个对象调用公有(public)的属性和方法访问类中成员或进行相应的操作。
从程序员的角度看,能够使用类的功能即可,不必关心类中的具体设计;
另一方面,从类设计的角度看,不需要也不能够向类之外的对象提供直接访问数据成员的功能,所以类中数据成员都设置为私有的(private),对外是不可见的。
这就是类的封装性。
SequencedList类的源代码放在SequencedList.cs文件中,本章将SequencedList等基础类定义在lists命名空间,而将使用这些基础类的测试类定义在liststest命名空间。
2.2.2顺序表的操作
1)顺序表的初始化
使用构造方法创建顺序表对象,为顺序表分配存储空间,并设置顺序表为空状态。
算法如下:
//构造空顺序表,分配c个存储单元
publicSequencedList(intc){
capacity=c;
items=newT[capacity];
//所占用的存储单元个数等于capacity
count=0;
//此时顺序表长度为0
//不带参数时,构造具有16个存储单元的空表
publicSequencedList():
this(16){}
重载的构造方法以一个数组的多个元素构造顺序表。
//以一个数组的多个元素构造顺序表
publicSequencedList(T[]itemArray){
count=itemArray.Length;
//顺序表长度
capacity=count+16;
count;
items[i]=itemArray[i];
2)返回顺序表长度
publicintCount{get{returncount;
}}
在SequencedList类中将返回顺序表长度的功能定义为类的属性成员,相对于方法成员显得更简洁,方法的调用必须加上括号,而属性的调用无须括号。
在前面的例子中我们也看到,C#用数组对象的Length属性获取数组的存储单元个数,如a.Length返回数组a的元素个数,此时Length后没有括号。
3)判断顺序表的空状态
当count等于0时,顺序表为空状态。
后面将看到,顺序表分配的存储空间可以根据需要而调整调整,编程时一般可以认为系统所提供的可用空间是足够大的,因此不必判断顺序表是否已满。
如果空间已用完,系统无法分配新的存储单元,则产生运行时异常。
//判断顺序表是否空
publicboolEmpty{get{returncount==0;
}}
4)获取或设置顺序表的容量
私有数据成员capacity表示顺序表的当前容量,定义公有属性Capacity供外部获取或设置顺序表的容量。
获取顺序表的容量,仅是简单地返回数据成员capacity的当前值。
设置顺序表的新容量,则是依次进行以下操作:
重新分配指定大小的存储空间作为顺序表的“数据仓库”,将原数组中的数据元素逐个拷贝到新数组,并设置capacity的新值。
后面将看到,当count等于capacity时,顺序表当前分配的存储空间已装满数据元素,进行后续的操作前,需要调用Capacity属性重新分配存储空间。
publicintCapacity{
get{returncapacity;
set{
capacity=value;
T[]copy=newT[capacity];
//createnewlysizedarray
if(count>
capacity)count=capacity;
Array.Copy(items,copy,count);
//copyoverthearray
items=copy;
//assignitemstothenewarray
5)获取或设置指定位置的数据元素值
就像C#的数组下标从0开始一样,我们用从0开始的索引参数i来指示顺序表的第i个元素。
//声明索引器以提供对类的实例进行类似于数组的访问;
获得或设置顺序表的第i个数据元素值
publicTthis[inti]{
get{
if(i>
=0&
&
i<
count)
returnitems[i];
else
thrownewIndexOutOfRangeException(
"
IndexOutOfRangeExceptionin"
+this.GetType());
set{
count){
items[i]=value;
}else{
6)查找具有特定值的元素
在线性表中查找具有特定值k的元素的过程为:
从线性表的第一个数据元素开始,依次比较线性表中的数据元素是否等于k,若当前数据元素与k相等,则查找成功;
否则继续与下一个数据元素进行比较,当比较完线性表的全部数据元素后仍未找到,则返回查找不成功信息。
上述操作分别用Contains方法和IndexOf方法实现,Contains方法查找成功时返回true,否则返回false。
IndexOf方法查找成功时返回k值首次出现位置,否则返回-1。
//查找线性表是否包含k值,查找成功时返回true,否则返回false
publicboolContains(Tk){
intj=IndexOf(k);
if(j!
=-1)
returntrue;
else
returnfalse;
//查找k值在线性表中的位置,查找成功时返回k值首次出现位置,否则返回-1
publicintIndexOf(Tk){
intj=0;
while(j<
count&
k.Equals(items[j]))
j++;
if(j>
j<
returnj;
else
return-1;
7)在顺序表的指定位置插入数据元素
要想在顺序表的第i个位置上插入给定值k,使得插入后的线性表仍然保持连续性,首先必须将第n-1到第i个位置上的数据元素依次向后移动一个位置,即依次向后移动从an-1到ai的数据元素,空出
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 线性