文章目录
线性表
一、线性表的定义
线性表(List):零个或多个数据元素的有限序列。
线性表(Linear List):n(n≥0)个数据元素a1, a2, …, an 组成的有限序列,一般记作 List=(a1,a2,…,an)
其中, List为线性表的名字。数据元素的个数n定义为表的长度。 当 n=0 时称为空表,记作 ( ) 或 ∅
在较复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表又称为文件
1.线性表的顺序表示
顺序表(Sequential List) :用顺序存储的线性表,即把线性表的结点按逻辑次序依次存放到一组地址连续的存储单元里 。
只要确定好了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的储存结构,因为高级语言中的数组类型也是有随机存取的特性,所以通常我们都使用数组来描述数据结构中的顺序储存结构,用动态分配的一维数组表示线性表。
2.线性表的结构
typedef int Elemtype ; //结点的数据类型,假设为int
const int maxsize=100 ; //最大表长度,假设为100
typedef struct {
Elemtype elem[maxsize] ; //第一个结点是elem[0]
int length; //当前长度
} Sqlist1 ; //顺序表类型
typedef int Elemtype ; //结点的数据类型,假设为int
typedef struct {
Elemtype *elem ; //第一个结点是elem[0]
int length; //当前长度
int listsize ; //当前分配容量
} Sqlist ; //顺序表类型
3.建立空表
Status InitList(SqList* L){
//构造一个空的线性表L
L -> elem = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
if(!L -> elem){
return ERROR;
}
L -> length = 0;
return OK;
}
4.顺序表的插入
int ListInsert ( Sqlist *L, ElemType x, int i )
{
//将x插入到顺序表L的第 i 个位置上
int j ;
if ( L−>n == maxsize )
{ cout <<”表满,不能插入!(上溢)\n”; return −1 ; }
if ( i<1 || i>L−>n+1 )
{ cout << ”非法插入位置!\n”; return 0 ; }
for ( j=L−>n ; j>=i ; j−− )
L−>elem[ j ] = L−> elem[ j−1 ] ; //结点后移
L−> elem[ i−1] = x ; //插入x,第i个结点的数组下标是i−1
L−>n++; //修改表长
return 1; //插入成功
}
5.顺序表的删除
将表的第i(1≤i≤n)个结点删去,使长度为n的线性表(a1,…,ai−1,ai,ai+1,…,an)变为长度为n−1的线性表(a1,…,ai−1,ai+1,…,an-1)。
int ListDelete( Sqlist *L, int i ) {
//从顺序表中删除第i个位置上的结点
int j;
if ( L−> length == 0 )
{ cout << ”表空,不能删除!(下溢)\n” ; return −1 ; }
if ( i<1 || i>L−>n )
{ cout << ”非法删除位置!\n” ; return 0 ; }
for ( j = i+1 ; j<=L−>n ; j++ )
L−>elem[j−2]=L−>elem[j−1] ; //结点前移
L−>n−−; //修改表长
return 1; //删除成功
}
6.获取顺序表某一位置上的元素
Status GetElem(SqList L, int i, ElemType *e){
if(L.length == 0 || i<1 || i>L.length){
return ERROR;
}
*e = L.elem[i-1];
return OK;
}
7.读取顺序表所有元素
/*打印线性表中的所有元素*/
void OutPut(SqList L){
printf("当前顺序表的长度:%d\n", L.length);
for(int i = 0; i < L.length; i++){
printf("%d ",L.elem[i]);
}
printf("\n");
}
二、线性表的链式表示
1.链表的定义
链表 (Linked List) :用链式存储的线性表,即用一组任意的存储单元存储线性表的各个数据元素,相互间的逻辑关系(前趋或后继)通过附加指针表示;所有结点通过指针域链接在一起,构成一个链表。
- 元素之间的逻辑关系通过附加指针表示;
- 结点可以连续,可以不连续;
- 结点的逻辑顺序与物理顺序可以不一致。
2.单链表
单链表(Singly Linked List):每个结点有两部分信息:数据域,存放结点的值(内容);指针域(亦称链域),存放结点后继的地址(或位置)。由于每个结点只有一个链域,故得名。
- 空指针:不指向任何结点
- 头指针:单链表第一个结点的地址
3.单链表的存储结构
typedef int ElemType ; //结点数据类型,假设为int
typedef struct LNode {
ElemType data; // 数据域
struct LNode *next; // 指针域
} LNode, *LinkList;
LinkList head , p ;
4.单链表的插入
/**
* 单链表插入操作
* 初始条件:线性表L已存在
* 操作结果:在L中第pos个位置之前插入新的数据元素e,L的长度增加1
*/
Status ListInsert(LinkList *L, ElemType elem, int pos){
if(pos<1 || pos > (*L)->lenght+1){
return ERROR;
}
//寻找第pos个结点
Node *p = (*L)->next; //头结点
for(int i=1; i<pos; i++){
p = p->next;
}
//生成一个新结点
Node *q = (Node *) malloc(sizeof(Node));
q->data = elem;
q->next = p->next; //将p的后继赋值给q的后继
p->next = q; //将q赋值给p的后继
(*L)->lenght += 1; //链表长度加1
return OK;
}
5.单链表的删除
int delete(LinkList head,int i)
{ LinkList p,q;
q= LocateElem_L(head,i−1); //找待删点的直接前趋
if(q==NULL || q−>next==NULL)
//即i<1或i>n时
{cout<<”非法删除位置!\n”;return 0;}
p=q−>next; //保存待删点地址
q−>next=p−>next; //修改前趋的后继指针
delete p; //释放结点
return 1; //删除成功
}
6.建表(头插法)
LinkList creat() //头插法建表,有头结点
{ LinkList head;
LinkList s;
char ch;
head=new Lnode; //生成头结点
while(cin>>ch,ch!=’$’) //输入并检测结束
{ s=new Lnode; //生成新结点
s−>data=ch; //装入数据
s−>next=head−>next;
head−>next=s; //插到头结点后
}
return head;
}
7.建表(尾插法)
LinkList creat() //尾插法建表,有头结点
{ LinkList head,rear,s;
char ch;
head=new Lnode; //生成头结点
rear=head; //尾指针初值
while(cin>>ch,ch!=’$’) //读入并检测结束
{ s=new Lnode; //生成新结点
s−>data=ch;
rear−>next=s; //新结点插入表尾
rear=s; //修改尾指针
}
rear−>next=NULL; //尾结点的后继为空
return head;
}
8.初始化
LinkList initlist()
{ LinkList head;
head=new Lnode;
head−>next=NULL;
return head;
}
9.单链表长度
int ListLength_L(LinkList L)
{ int j;
LinkList p;
j=0;
p=L->next; //从首结点开始
while(p!=NULL) //逐点检测、计数
{ j++;
p=p->next;
}
return j;
}
10.按值查找
LinkList LocateElem1_L(LinkList L,ElemType x)
{ LinkList p;
p=head−>next; //从首结点开始搜索
while(p!=NULL)
{ if(p−>data==x) break;
p=p−>next; //到下一个点
}
return p;
}
int LocateElem2_L(LinkList head, ElemType x)
{ int j;
LinkList p;
j=0; //计数器
p=head−>next; //从首结点开始扫描
while(p!=NULL) {
j++;
if(p−>data==x) break; //找到,退出
p=p−>next; //没找到,继续
}
if(p!=NULL) return j; //找到x
else return −1; //没有x,查找失败
}
11.清空单链表
Status Clear(LinkList *L){
Node *p = (*L)->next->next, *q;
while(p != NULL){
q = p;
p = p->next;
free(q);
}
(*L)->next->next = NULL;
(*L)->lenght = 0;
return OK;
}
12.销毁单链表
Status Destory(LinkList *L){
Node *p = (*L)->next, *q;
while(p != NULL){
q = p;
p = p->next;
free(q);
}
free((*L));
(*L) = NULL;
return OK;
}
如果你喜欢本博文,可以点点关注,以后会不断更新哦