线性表是由同一类型的数据元素构成的有序序列的线性结构, 线性表中元素的个数称为线性表的长度。线性表中元素的前一个元素叫做当前元素的直接前驱;后一个元素叫做当前元素的直接后继。
线性表的顺序储存
线性表的顺序存储指的是内存中使用地址连续的一块存储空间顺序存放线性表的各元素。一般利用一维数组来表示顺序存储的数据区域,同时需要用一个Last变量来记录当前线性表中最后一个元素在数组中的位置,所以通常将数组变量Data和变量Last封装成一个数据结构作为顺序表的类型。
typedef int Position;
/*position是数组的整数下标,从0开始,前面提到的位序是从1开始。*/
typedef struct LNode *PtrToLNode;
struct LNode{
ElementType Data[MAXSIZE];
Position Last;
};
typedef PtrToLNode List;
/*可以利用List定义线性表*/
/*线性表长度可以通过L->Last+1得到*/
初始化
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));
L->Last = -1;
return L;
}
查找
查找与给定值相同的数据元素
#define ERROR -1
Position Find(List L, ElementType X)
{
Position i = 0;
while(i<=L->Last && L->Data[i]!= x)
i++;
if(i > L->Last)
return ERROR;
else
return i;
}
插入
在表的第i个位序上插入一个值为X的新元素
bool Insert(List L, ElementType X, int i)
{
/*在L的指定位序i前插入一个新元素X*/
Position j;
if(L->Last == MAXSIZE-1){
print("FULL");
return false;
}
if(i<1 || i>L->Last+2){
print("illegal");
return false;
}
else{
for(j=L->Last; j>=i-1; j--) /*Last指向最后一个元素*/
L->Data[j+1] = L->Data[j]; /*将位序i及之后的元素往后移动*/
L->Data[i-1] = X; /*将X插入到位序i上*/
L->Last++; /*原始数组长度加一*/
return true;
}
}
删除
将表中位序 为i的元素从表中去掉
bool Delete(List L, int i)
{
/*从L中删除位序i的元素*/
Position j;
if(i<1 || i>L->Last+1){
print('order does not exist');
return false;
}
else{
for(j=i; j<=L->Last; j++)
L->Data[j-1] = L->Data[j]; /*将位序i+1及以后的元素往前移动*/
L->Last--; /*线性表长度减一*/
return true;
}
}
线性表的链式存储
通过“链”建立起数据元素之间的逻辑关系,这时候每个数据单元由数据域和链接域两部分组成。
typedef struct LNode *PtrToLNode;
struct LNode{
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Postion; /*Postition是结点的地址*/
typedef PtrToLNode List;
/*List L可以定义一个链式表*/
求表长
int Length(List L)
{
Position p;
int cnt=0; /*初始化计数器*/
p = L; /*p指向表的第一个结点*/
while(p){
p = p->Next;
cnt++; /*当前p指向的是第cnt个结点*/
}
return cnt;
}
查找
查找有两种方式,按序号查找和按值查找
/*按序号查找*/
#define ERROR -1;
ElementType FindKth(List L, int K)
{
Position p;
int cnt = 1;
p = L;
while(p && cnt<K){
p = p->Next;
cnt++;
}
if((cnt == K) && p)
return p->Data;
else
return ERROR;
}
/*按值查找*/
#define ERROR NULL
Position Find(List L, ElementType X)
{
Position p = L; /*p指向L的第1个结点*/
while(p && p->Data != x)
p = p->Next;
if(p)
return pl
else
return ERROR;
}
插入
在指定位序i前插入一个新元素X
bool Insert(List L, ElementType X, int i)
{
/*默认线性表有头结点*/
Position tmp, pre;
int cnt = 0;
/*查找位序为i-1的结点*/
pre = L;
while(pre && cnt < i-1){
pre = pre->Next;
cnt ++;
}
/*所查结点不在L中*/
if(pre==NULL || cnt!=i-1){
print("Position Error");
return false;
}
/*找到了待插结点的前一个结点pre*/
else{
tmp = (Position)molloc(sizeof(struct LNode)); /*申请、填装结点*/
tmp->Data = x;
tmp->Next = Pre->Next;
pre->Next = tmp;
return true;
}
}
删除
删除结点,释放空间
bool Delete(List L, int i)
{
/*默认L有头结点*/
Position tmp, pre;
int cnt = 0;
/*查找位序为i-1的结点*/
pre = L; /*指向表头*/
while(pre && cnt<i-1){
pre = pre->Next;
cnt ++;
}
/*所找结点和位序不在L中*/
if(pre==NULL || cnt!=i-1 || pre->Next==NULL){
print("ERROR");
return false;
}
esle{
/*删除节点*/
tmp = pre->Next;
pre->Next = tmp->Next;
free(tmp);
return true;
}
}
广义表
广义表是线性表的推广,同样是n个元素组成的有序序列,但是在广义表中这些元素可以是单元素也可以是另一个广义表。
typedef struct GNode *PtrToGNode
typedef PtrToGNode GList
struct GNode{
int Tag; /*标志域:0表示单元素;1表示广义表*/
union{
/*子表指针域Sublist与单元素数据域Data复用,共享存储空间*/
ElementType Data;
GList Sublist;
}URegion;
PtrToGNode Next;
}
多重链表
链表中的结点不属于单个链的链表称为“多重链表”,一般来说,多重链表中每个结点的指针域会有多个,典型的多重链表有十字链表。
用十字链表来存储稀疏矩阵,非0元素的结点由两个指针域,行指针和列指针,用于存放元素的行坐标、列坐标和数值。
typedef enum{Head, Term} NodeTag;
struct TermNode{
/*非零元素结点*/
int Row, Col;
ElementType Value;
};
typedef struct MNode *PtrToMNode;
struct MNode{
/*矩阵结点定义*/
PtrToMNode Down, Right;
NodeTag Tag;
union{
/*Head是Next指针,Term是非零元素结点*/
PtrToMNode Next;
struct TermNode Term;
}URegion;
}
参考书籍:《 数据结构》第二版,陈越,何钦铭等,高等教育出版社。