我们终于可以学习第一个数据结构的知识了!首先先了解线性表的概念 定义:
线性表 是由零个或多个相同类型的元素 组成的有限序列 。每个元素在表中都有一个前驱元素(除第一个元素外)和后继元素(除最后一个元素外)
线性表的两种常见实现方式:
由定义可知由n(n>=0)个数据特性相同的元素构成的有限序列,称为线性表 ,即线性表是n个数据元素的有限序列,其中n个数据是相同数据类型的
线性表中元素个数 n(n>=0) 定义为线性表的长度 ,当n等于零时称之为空表
对于非空的线性表或线性结构,其特点是:
存在唯一的一个被称作”第一个”的数据元素 并且 存在唯一的一个被称作”最后一个”的数据元素除第一个元素外,
结构中的每个数据元素均只有一个前驱(即前一个元素) 以及 除最后一个元素外,结构中的每个数据元素均只有一个后驱(即后一个元素)
这个我们先讲顺序表
顺序表
顺序表 (即数组 )是一种线性表 的数据结构,它包含一组相同类型的数据元素,这些元素按顺序存储在连续的内存空间中。每个元素在顺序表中的位置是固定的,可以通过索引(下标)直接访问
由定义可以知道 , 我们前几篇中回顾的struct结构体不是顺序表,而是一个容器,因为结构体中的元素是无序的,而像数组这样每个索引元素的位置是固定的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> #include <stdlib.h> #include <string.h> struct book { int isbn; char bookName[20 ]; double price; }; int main () { struct book b ; b.isbn=767645 ; strcpy (b.bookName,"Dune" ); b.price=70 ; return 0 ; }
可以看出访问结构体成员没有顺序
顺序表的特点
元素类型必须相同 。所有元素都必须是同一种数据类型(例如,都为 int,float 等)
元素按顺序存储 ,每个元素都有一个确定的位置,可以通过下标访问
**可以是静态的(如固定大小数组)**或动态的(如通过动态内存分配的数组)
以下所有功能我都会封装在函数里,3个语言都是,你们在main函数里修改一下即可
什么 你问我为啥另外两种语言 用lua 和 C# 而不是 Java 和 C++ ? emmm , 当然是我现在正在学习Unity 和 Love2d做游戏,而这两个游戏引擎分别使用C# 和 Lua写脚本 (毕竟我想把学到的东西快速投入到实践中,只是目前还不知道数据结构有什么用 狗头狗头狗头 )
顺序表的初始化 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdio.h> #define MAXSIZE 100 typedef int ElemType;typedef struct { ElemType data[MAXSIZE]; int length; }SeqList; void initList (SeqList*L) { L->length=0 ; } int main () { SeqList list ; initList(&list ); printf ("初始化成功,目前长度占用%d\n" ,list .length); printf ("目前占用内存%zu字节\n" ,sizeof (list .data)); return 0 ; }
Lua版本 用lua表示就是如下
lua因为比较自由没有太多的限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 local SeqList = {}SeqList.__index = SeqList function SeqList:new () local instance = setmetatable ({}, SeqList) instance:initList() return instance end function SeqList:initList () self .data = {} end function SeqList:getLength () return #self .data end local function main () local list = SeqList:new() print (string .format ("初始化成功, 目前长度占用:" .. list:getLength())) end main()
C#版本 在C#里我们可以用面向对象的思想来实现顺序表的初始化,在C#里 List 类似于C里面的数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 using ElemType = System.Int32;public class SeqList { public List<ElemType> data = new List<ElemType>(); public int length { get { return data.Count; } } public SeqList () { initList(); } public void initList () { data = new List<ElemType>(); } } class Program { static void Main (string [] args ) { SeqList list = new SeqList(); Console.WriteLine($"初始化成功,目前长度占用{list.length} " ); Console.WriteLine($"目前内部数组容量(Capacity): {list.data.Capacity} " ); } }
顺序表的尾插法 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int appendElem (SeqList*L,ElemType e) { if (L->length>=MAXSIZE){ printf ("顺序表已满\n" ); return 0 ; } L->data[L->length]=e; L->length++; return 1 ; } int main () { SeqList list ; initList(&list ); printf ("初始化成功,目前长度占用%d\n" ,list .length); printf ("目前占用内存%zu字节\n" ,sizeof (list .data)); appendElem(&list ,88 ); return 0 ; }
Lua版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function SeqList:appendElem (e) table .insert (self .data, e) return 1 end local function main () local list = SeqList:new() print (string .format ("初始化成功, 目前长度占用:" .. list:getLength())) list:appendElem(88 ) list:appendElem(100 ) print (string .format ("目前长度占用:" .. list:getLength())) print (string .format ("第一个元素: %d, 第二个元素: %d" , list.data[1 ], list.data[2 ])) end main()
C#版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class SeqList { public int appendElem (int e ) { data.Add(e); return 1 ; } } class Program { static void Main (string [] args ) { SeqList list = new SeqList(); Console.WriteLine($"初始化成功,目前长度占用{list.length} " ); list.appendElem(88 ); Console.WriteLine($"目前长度占用: {list.length} " ); } }
顺序表的遍历 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void listElem (SeqList *L) { for (int i=0 ;i<L->length;i++){ printf ("%d " ,L->data[i]); } printf ("\n" ); } int main () { SeqList list ; initList(&list ); printf ("初始化成功,目前长度占用%d\n" ,list .length); printf ("目前占用内存%zu字节\n" ,sizeof (list .data)); appendElem(&list ,88 ); appendElem(&list ,45 ); appendElem(&list ,43 ); appendElem(&list ,17 ); listElem(&list ); return 0 ; }
Lua版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function SeqList:listElem () for v in ipairs (self .data) do io .write (v .. "\n" ) end print (table .concat (self .data, "\n" )) end local function main () local list = SeqList:new() list:appendElem(88 ) list:appendElem(100 ) print ("顺序表元素如下:" ) list:listElem() end main()
C#版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class SeqList { public void listElem () { foreach (var item in data) { Console.WriteLine(item); } Console.WriteLine(string .Join("\n" , data)); } } class Program { static void Main (string [] args ) { SeqList list = new SeqList(); list.appendElem(23 ); list.appendElem(45 ); list.appendElem(88 ); Console.WriteLine("顺序表的元素有:" ); list.listElem(); } }
顺序表的删除 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int deleteElem (SeqList*L,int pos,ElemType*e) { if (L->length==0 ){ printf ("空表\n" ); return 0 ; } if (pos<1 ||pos>L->length){ printf ("删除数据位置有误\n" ); return 0 ; } *e=L->data[pos-1 ]; if (pos<L->length){ for (int i=pos;i<L->length;i++){ L->data[i-1 ]=L->data[i]; } } L->length--; return 1 ; } int main () { SeqList list ; initList(&list ); appendElem(&list ,88 ); appendElem(&list ,45 ); appendElem(&list ,43 ); appendElem(&list ,17 ); listElem(&list ); ElemType delData; deleteElem(&list ,2 ,&delData); printf ("被删除的数据为:%d\n" ,delData); listElem(&list ); return 0 ; }
Lua版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 function SeqList:deleteElem (pos) if #self .data == 0 then print ("空表" ) return nil end if pos < 1 or pos > #self .data then print ("删除数据位置有误" ) return nil end local e = table .remove (self .data, pos) return e end local function main () local list = SeqList:new() list:appendElem(88 ) list:appendElem(100 ) print ("顺序表元素如下:" ) list:listElem() local delData = list:deleteElem(2 ) print ("删除第2个位置的数据后,被删除的数据为:" .. delData) list:listElem() list:deleteElem(2 ) print ("删除第2个位置的数据后,顺序表元素如下:" ) list:listElem() end main()
C#版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class SeqList { public int deleteElem (int pos, out ElemType e ) { e = 0 ; if (length == 0 ) { Console.WriteLine("空表" ); return 0 ; } if (pos < 1 || pos > length) { Console.WriteLine("删除数据位置有误" ); return 0 ; } e = data[pos - 1 ]; data.RemoveAt(pos - 1 ); return 1 ; } } class Program { static void Main (string [] args ) { SeqList list = new SeqList(); list.appendElem(23 ); list.appendElem(45 ); list.appendElem(88 ); Console.WriteLine("顺序表的元素有:" ); list.listElem(); ElemType deletedElem; list.deleteElem(2 , out deletedElem); list.listElem(); Console.WriteLine("被删除的元素是:" + deletedElem); } }
顺序表的指定位置插入 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int insertElem (SeqList*L,int pos,ElemType e) { if (L->length>=MAXSIZE){ printf ("表已经满了\n" ); return 0 ; } if (pos<1 ||pos>L->length){ printf ("插入位置错误\n" ); return 0 ; } if (pos<=L->length){ for (int i=L->length-1 ;i>=pos-1 ;i--){ L->data[i+1 ]=L->data[i]; } L->data[pos-1 ]=e; L->length++; } return 1 ; } int main () { SeqList list ; initList(&list ); printf ("初始化成功,目前长度占用%d\n" ,list .length); printf ("目前占用内存%zu字节\n" ,sizeof (list .data)); appendElem(&list ,88 ); appendElem(&list ,45 ); appendElem(&list ,43 ); appendElem(&list ,17 ); listElem(&list ); insertElem(&list ,2 ,18 ); listElem(&list ); return 0 ; }
顺序表的查找 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 int findElem (SeqList*L,ElemType e) { if (L->length==0 ){ printf ("空列表\n" ); return 0 ; } for (int i=0 ;i<L->length;i++){ if (L->data[i]==e){ return i+1 ; } } return 0 ; } int main () { SeqList list ; initList(&list ); appendElem(&list ,88 ); appendElem(&list ,45 ); appendElem(&list ,43 ); appendElem(&list ,17 ); listElem(&list ); insertElem(&list ,2 ,18 ); listElem(&list ); int number=1 ; printf ("找到%d位置的数据值为%d" ,number,findElem(&list ,number)); return 0 ; }
顺序表的动态分配内存并初始化 C版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 SeqList* initList () { SeqList*L=(SeqList*)malloc (sizeof (SeqList)); L->data =(ElemType*)malloc (sizeof (ElemType)*MAXSIZE); L->length=0 ; return L; } int main () { SeqList *list =initList(); appendElem(list ,88 ); appendElem(list ,45 ); appendElem(list ,43 ); appendElem(list ,17 ); listElem(list ); insertElem(list ,2 ,18 ); listElem(list ); printf ("%d\n" ,findElem(list ,40 )); return 0 ; }
暂时没有精力去兼顾lua和C#版本的吧,毕竟快考试了,以后我再慢慢补票吧
评论区