数据结构——线性表
头指针或者尾指针需要改变,并且需要把改变的值带回到主程序,带回到调用处需要用到指针的指针;
当尾指针不发生改变,或者即使发生了改变也不希望带回到主程序当中就用指针;
1 线性表的定义
线性表的元素是有限的,元素之间有顺序的一个挨着一个
数学定义:
将线性表标记为以序列:
a1,a2,a3,...,ai-1,ai,ai+1,...,an
序列中ai-1位于ai的前面,称ai-1是ai的直接前驱;
序列中ai+1位于ai的后面,称ai+1是ai的直接后继;
a1仅有直接后继,an仅有直接前驱;
2 线性表的抽象数据类型
ADT线性表(Abstract Data Type抽象数据类型)
data
a1,a2,a3,...,ai-1,ai,ai+1,...,an
operation
InitList(L) 初始化操作建立一个空的线性表
ListEmpty(L) 若线性表为空,返回true
若线性表不为空,返回false
ClearList(L) 将线性表中的所有元素删除
GetElement(L,i) 返回线性表L中下标为i的元素
LocateElement(L,e) 在线性表L中查找指定元素e
若查找成功,返回e在L的下标中
若不成功,返回-1
InsertInit(L,i,e) 在线性表L中下标为i的位置插入元素e
DeleteList(L,i) 将线性表L中下标为i的元素删除
ListLength(L) 返回线性表L中元素的个数;线性表的长度就是表中保存的数据元素的个数
endADT
3 顺序存储结构
用一段地址连续的存储空间,依次存储线性表中的数据元素(数组可以实现连续存储)
示意图:
a1 |
a2 |
... |
ai-1 |
ai |
ai+1 |
... |
an |
4 线性表的顺序表存储结构
#define LISTSIZE 100
typedef int DataType;
typedef struct SeqList //typedef作用给结构体起了一个别名叫SeqList,红色部分作用相当于int
{ //给结构体起别名是为了后面调用结构体的时候不用敲struct,否则调用时要struct SeqList
DataType data[LISTSIZE];
int nLength; //线性表元素个数
}SeqList;
数据长度:线性表中能保存的数据元素最多个数,是一个固定值
线性表长度:线性表中已经保存的数据元素个数,是一个随时变化的值
地址计算:
地址(address):存储器中每个存储单元的编号
address(ai)=address(ai-1)+n
=address(a0)+n*(i-1)
n:每个元素所占的字节
下标(subscript):数组中每个元素的编号
4.1 初始化操作
void InitList(SeqList *list) { list->nLength=0; }
sl是一个线性列表,程序运行时会给sl分配一个存储空间,当调用函数initList后,相当于指针变量list保存了sl的地址,占4个字节。
4.2 判断表是否为空
void ListEmpty(SeqList *list) { return list->nLength==0; }
4.3 将线性表中的所有元素删除
void clearList(SeqList *list) { list->nLength=0; }
4.4 获取线性表L中元素个数
int listLength(SeqList *list) { return list->nLength; }
4.5 获取线性表中下标为i的元素
#define LISTSIZE 100 typedef int DataType; typedef struct SeqList { DataType data[LISTSIZE]; int nLength; }SeqList; DataType *getNode(SeqList *list,int i) { if(i<0 || i>list->nLength-1) return NULL; //NULL代表没有数据存在 return &list->data[i]; }
4.6 在线性表中查找指定元素
int LocateNode(SeqList *list,DataType x) { for(int i=0;i<list->nLength;i++) if(list->data[i]==x) return i; return -1 }
4.7 在线性表中下标为i的位置插入元素
#define LISTSIZE 100 typedef int DataType; typedef struct SeqList { DataType data[LISTSIZE]; int nLength; }SeqList; bool insert(SeqList *list,int i ,DataType x) { if(list->nLength==LISTSIZE) return flase; int insertPositon=i; if(i<0) insertPositon=0; if(i>list->nLength-1) insertPositon=list->nLength; for(int j=list->nLength-1;j>=insertPositon;j--) list->data[j+1]=list->data[j]; list->data[insertPositon]=x; list->nLength++; return true; } void main() { SeqList sl; ... insert(&sl,5,10); //在第五个位置插入元素10 }
4.8 删除线性表中下标为i的元素
#define LISTSIZE 100 typedef int DataType; typedef struct SeqList { DataType data[LISTSIZE]; int nLength; }SeqList; bool deleList(SeqList *list,int i) { if(i<0 || i>=list->nLength) return false; for(int j=i;j<list->nLength;j++) list->data[j]=list->data[j+1]; list->nLength--; return true; } void main() { SeqList sl; ... deleList(&sl,3); //删除下标为3的元素 }
4.9 将两个线性表合并
void union(SeqList *a,SeqList *b) { if(a->nLength + b->nLength >LISTSIZE) return; for(int i=0;i<b->nLength;i++) { DataType e=b->data[i]; if(locadeNode(a,e)==-1) //在线性表中查找指定元素 insert(a,a->nLength,e); //在线性表中下标为i的位置插入元素 } }
4.10 将线性表倒置
void reverse(SeqList *list) { for(int i=0;i<list->nLength/2;i++) { DataType t=list->data[i]; list->data[i]=list->data[list->nLength-1-i]; list->data[list->nLength-1-i]=t; } }
4.11 线性表遍历
void print(DataType d) { printf("%d\n",d); } void trave(SeqList *list,void(visitFun)(DataType)) { for(int i=0;i<list->nLength;i++) { visitFun(list->data[i]); } } void main() { SeqList sl; ... trave(&sl,print); }