目录
目录
线性表基本操作
InitList(&L):初始化表。构造一个空的线性表。
Length(L):求表长。返回线性表L的长度,即L中数据元素的个数。
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。
GetElem(L,i):按位查找操作。获取表L中第 i 个位置的元素的值。
ListInsert(&L,i,e):插入操作。在表L中的第 i 个位置上 插入指定元素e。
ListDelete(&L,i,&e):删除操作。删除表L中第 i 个位置的元素,并用e返回删除元素的值。
PrintList(L):输出操作。按前后顺序输出线性表L的所有元素值。
Empty(L):判空操作。若L为空表,则返回true,否则返回false。
DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
顺序存储
线性表的顺序存储类型描述为:
线性表的元素类型为ElemType.
1->静态分配
#define Maxsize 50//定义线性表的最大长度
typedef struct{
ElemType data[Maxsize];//顺序表的元素
int length;//顺序表的当前长度
}SqList;//顺序表的类型定义
2->动态分配
#define InitSize 100//表长度的初始定义
typedef struct{
ElemType *data;//指示动态分配数组的指针
int MaxSize,length;//数组的最大容量和当前个数
}SeqList; //动态分配数组顺序表的类型定义
动态分配空间
C的初始动态分配语句
L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);
C++的初始动态分配语句
L.data=new ElemType[InitSize];
插入操作
bool ListInsert(SqList &L,int i,ElemType e){//平均时间复杂度O(n)
if(i<1||i>L.length+1)//判断i的范围是否有效
return false;
if(L.length>=MaxSize)//当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--)//将第i个元素及之后的元素后移
{
L.data[j]=L.data[j-1];
}
L.data[i-1]=e;//在位置i处放入e
L.length++;//线性表长度加1
return true;
}
删除操作
bool ListDelete(SqList &L,int i,ElemType &e){//平均时间复杂度O(n)
if(i<1||i>L.length)//判断i的范围是否有效
return false;
e=L.data[i-1];//将被删除的元素赋值给e
for(int j=i;j<L.length;j++)//将第i个位置后的元素前移
L.data[j-1]=L.data[j];
L.length--;//线性表长度减1
return true;
}
按值查找(顺序查找)
int LocateElem(SqList L,ElemType e){
//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
int i;
for(i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;//下标为i的元素值等于e,返回其位序i+1
return 0;//退出循环,说明查找失败
}//平均时间复杂度O(n)
链式存储
单链表中结点类型描述
typedef struct LNode{//定义单链表结点类型
ElemType data;//数据域
struct LNode *next;//指针域
}LNode,*LinkList;
头插法建立单链表
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode));//创建头结点
L->next=NULL;//初始为空链表
scanf("%d",&x);//输入结点的值
while(x!=9999){//输入9999表示结束
s=(LNode*)malloc(sizeof(LNode));//创建新结点
s->data=x;
s->next=L->next;
L->next=s;//将新结点插入表中,L为头指针
scanf("%d",&x);
}
return L;
} //单链表长为n,总时间复杂度为O(n)
尾插法建立单链表
LinkList List_TailInsert(LinkList &L){//正向建立单链表
int x;//设元素类型为整型
L=(LinkList)malloc(sizeof(LNode));
LNode *s,*r=L;//r为表尾指针
scanf("%d",&x);//输入结点的值
while(x!=9999){//输入9999表示结束
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;//r指向新的表尾结点
scanf("%d",&x);
}
r->next=NULL;//尾结点指针置空
return L;
}
按序号查找结点值
LNode *GetElem(LinkList L,int i){//查找操作时间复杂度O(n)
int j=1;//计数,初始为1
LNode *p=L->next;//第1个结点指针赋给p
if(i==0)
return L;//返回头结点
if(i<1)
return NULL;//若i无效,则返回NULL
while(p&&j<i){//从第1个结点开始找,查找第i个结点
p=p->next;
j++;
}
return p;//返回第i个结点的指针,若i大于表长,则返回NULL
}
按值查找表结点
LNode *LocateElem(LinkList L,ElemType e){O(n)
LNode *p=L->next;
while(p!=NULL&&p->data!=e)//从第1个结点开始查找data域为e的结点
p=p->next;
return p;//找到后返回该结点指针,否则返回NULL
}
插入结点操作
1->后插(查找为O(n),插入为O(1))
p=GetElem(L,i-1);//查找插入位置的前驱结点
s->next=p->next;
p-next=s;
2->前插(转化为后插)
交换*s与*p,既满足逻辑关系,又使时间复杂度为O(1)
p=GetElem(L,i-1);//查找插入位置的前驱结点
s->next=p->next;
p-next=s;
temp=p->data;//交换
p->data=s->data;
s->data=temp;
删除结点操作
p=GetElem(L,i-1);//查找删除位置的前驱结点 O(n)
q=p->next;//令q指向被删除结点
p->next=q->next;//将*q结点从链中“断开”
free(q);//释放结点的存储空间
双链表
typedef struct DNode{//定义双链表结点类型
ElemType data;//数据域
struct DNode *prior,*next;//前驱和后继指针
}DNode,*DLinkList;
插入操作
s->next=p->next;//将结点*s插入到结点*p之后
p->next->prior=s;
s->prior=p;
p->next=s;
删除操作
p->next=q->next;
q->next->prior=p;
free(q);
循环链表
在循环双链表L中,某结点*p为尾结点时,p->next==L;当循环双链表为空表时,其头结点的prior域和next域都等于L。