数据结构?从线性表开始
终于基本学完《C Prime Plus》了(其实还有位操作和编译器那块没看),不过已经能够看得懂《大话数据结构》的代码了,可以开始学习数据结构了!走起。
不得不说,《大话数据结构》这本书看的就让人舒服,色彩鲜艳,言语通俗易懂,很适合我这种不是为了考试而来学数据结构的人。别人都说学数据结构是非科班人学习IT过程中最痛苦的一个环节,到我这里,至少一开始还是能啃得动的~
书中第三章开始正式讲解数据结构,第一个讲的就是线性表。说到线性表,其实在学习C语言的时候就已经接触到了,没错就是数组~线性表的定义是零个或多个相同的数据元素的有序排列。这句话有两个关键点:相同元素、有序。什么意思呢?
- 元素都相同,要么都是int,要么都是字符串啥的。
- 有序,每个元素都有自己专属的排号。
元素相同意味着线性表是较为简单的数据结构,专门储存相同类型数据,有序意味着我们利用这种数据结构可以进行查找操作。
线性表分为两种表达方式:顺序存储和链表。
线性表的基本操作有:插入/删除、创建、查找。
顺序存储
顺序存储是一段地址连续的存储单元依次存储线性表。学习C语言时,数组就是这种数据结构的典型代表,内存空间连续,每个元素都有一一对应的下标(位置)。
创建顺序存储:
#define SIZE 20
typedef struct {
int data[SIZE];
int length;
}Sqlist;
顺序存储由两个成员组成:数组和线性表长度。数组就是线性表的数据域,线性表长度反映的是当前顺序存储线性表所存储的数据长度(元素的个数)。线性表长度和数组长度是不一样的,数组长度是给编译器看的,用来申请这个数组预留的内存空间,线性表长度是实时更新的变量。
顺序存储一个明显的优点--地址连续,这样意味着查询元素非常方便,只要获取到元素对应的位置,按数组名(首元素地址)加上位置量就可以找到要查找的那个确定位置的元素。对于顺序存储,查找操作时间长度仅为O(1)。
顺序存储的插入和删除
顺序存储线性表的插入和删除就没有查找那么容易了,因为顺序存储的地址是连续的,要插入,就必须让指定位置后面所有元素后移一位,删除就必须删掉后所有元素前移一位。
插入:
void ListInsert(Sqlist *L,int i,int e){//L是指向顺序存储的指针,i是要插入的位置,e是要插入的数据元素,
int k;
if (i<=SIZE){
for(k=L->length-1;k>=i-1;k--) L->data[k+1]=L->data[k]; //先进行元素后移操作
}
L->data[i-1]=e; //把元素插入进空出来的位子
L->length++; //不要忘记更新线性表长度
}
删除:
void ListDelete(Sqlist *L,int i,int *e){//L是指向顺序存储的指针,i是要删除的位置,e用来存下被删除的那个元素
int k;
*e = L->data[i-1];
if (i<=SIZE){
for(k=L->length-1;k<SIZE;k++) L->data[k-1]=L->data[k]; //进行元素前移操作
}
L->length--;//不要忘了更新线性表长度
}
可以看出,插入和删除的时间长度均为O(n),这是没办法的,顺序存储就是这样。
顺序存储的优缺点
优点:无须为表示表中元素之间的逻辑关系而增加额外的存储空间,因为表中元素的逻辑关系只有一个,就是按号排列好;可以快速存取、查找表中任意元素。
缺点:增删改查耗费时间;整体长度变化较大时,难以确定存储空间的容量;容易造成存储空间的“碎片”。