数据结构---线性表
2.1 线性表及其基本运算
一、线性表
线性表是n个数据元素的优先序列,记为L=(a1,a2,…)
数据元素之间的关系是:
ai-1领先于ai, ai领先于ai+1。
称ai-1是a;的直接前驱元素: ai+1是a;的直接后继元素。
除a外,每个元素有且仅有一一个直接前驱元素,
除a外,每个元素有且仅有一一个直接后继元素。
线性表中数据元素的个数n(n>=0)称为线性表的长度,当n=0时,称为空表。
线性表是最常用且最简单的一种数据结构。
ai领先于ai+1。
称ai-是a;的直接前驱元素: ai+1是a;的直接后继元素。
除a外,每个元素有且仅有一一个 直接前驱元素,
除a外,每个元素有且仅有一一个直接后继元素。
线性表中数据元素的个数n(n>=0)称为线性表的长度,当n=0时,称为空表。
二、基本运算
函数名 | 操作 | 内容 |
---|---|---|
Initiate(L) | 初始化操作 | 设定一个空的线性表 |
Length(L) | 求长度函数 | 函数值为线性表L中数据元素的个数 |
Get(L,i) | 取元素函数 | i∈[1,length]时返回L中第i个数据元素,否则为空元素NULL。i为该元素的位序。 |
Prior(L,elm) | 求前驱函数 | elm为L中的一个数据元素,若它位序大于1,则函数值为elm的前驱元素,否则为NULL。 |
Next(L,elm) | 求后继函数 | 若elm的位序小于表长n,则函数值为elm的后继,否则为NULL。 |
Locate(L,x) | 定位函数 | 给定值x,若x不在表中,则返回0,否则返回在表中第一次出现时的位序。 |
Insert(L,i,b) | 前插操作 | 在第i个元素之前插入新元素b,i的取值范围为:i∈(1,n+1);i=n+1表示在表尾插入,n为表长。 |
Delete(L,i) | 删除操作 | 删除线性表L中位序为i的元素。i∈(1,n); |
Empty(L) | 判空表操作 | 若L为空表,则返回布尔值"ture",否则返回布尔值"false" |
Clear(L) | 表置空操作 | 将L置为空表,没有返回值。 |
线性表中每个操作的单独实现
--------------------定义顺序线性表 -------------------
#include<stdio.h>
// 线性表 长度 存放元素类型
typedef int Ele;/* ElemType类型根据实际情况而定,这里假设为int */
typedef struct
{
Ele data[30]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
//Ele data[20]; /* 数组,存储数据元素 */
int length; /* 线性表当前长度 */
}List;
------------------初始化顺序线性表 -------------------
int Initiate(List *L)
{
L->length=20;
return 0;
}
--------------------求长度函数 -----------------------
int Length(List *L)
{
printf("%d\n",L->length); /返回线性表中数据元素的个数
return 0;
}
---------------------取元素操作------------------------
int Get(List L,int i)
{
if (L.length==0||i<1||i>L.length)
{
printf("Error\n");
}else{
printf("%c\n",L.data[i-1]);
}
return 0;
}
---------------------求前驱元素------------------------
int Prior(List L,int i)
{
if((i-1)!=0)
{
int k;
for(k=0;k<i;k++)
printf("%2d",L.data[k]);
printf("\n");
}else{printf("该元素没有前驱元素!\n");}
return 0;
}
---------------------求后继元素-------------------------
int Next(List L,int i)
{
int k;
if(i<L.length)
{
for(k=i;k<=L.length;k++)
printf("%3d",L.data[k]);
printf("\n");
}else{printf("该元素没有后继元素!\n");}
return 0;
}
---------------------定位元素-------------------------
int Locate(List L,int x)
{
int k=-1;
for(int i=0;i<L.length;i++)
if(x==L.data[i])
{
k=i+1;
}
if (k!=-1)
{
printf("该元素是第%d个元素\n",k);
}else{
printf("该元素不存在!\n");
}
return 0;
}
---------------------前插元素-------------------------
int Insert(List *L,int i,int x)
{
if(i<1||i>L->length+1)
{
printf("Error\n");
}else
{
int k;
for(k=L->length;k>=i;k--)
L->data[k+1]=L->data[k];
}
L->data[i]=x;
L->length++;
return 0;
}
---------------------删除元素-------------------------
int Delete(List *L,int i)
{
if(i<0||i>L->length)
{
printf("删除不合法,Error\n");
}else{
int k;
for(k=i;k<L->length;k++)
L->data[k]=L->data[k+1];
}
L->length--;
return 0;
}
---------------------判空操作-------------------------
int Checkout(List L)
{
int i;
for(i=0;i<L.length+1;i++)
{
if(L.data[i])
printf("表非空\n");
break;
}
return 0;
}
---------------------清空表操作------------------------
int Clear(List *L)
{
int i;
for(i=0;i<L->length+1;i++)
if(L->data[i]!=0)
L->data[i]=0;
return 0;
}
执行后:
例:求两个集合的并,即A=A∪B
分析:设A、B分别由两个线性表LA和LB表示,要求将LB中存在而LA中不存在的DE插入到表LA中。
算法思想:
①依次从LB中取出一个DE;
②判在LA中是否存在;
③若不存在,则插入到LA中。
例:归并两个有序的线性表LA和LB为一一个新的有序线性表LC。
算法思想:
①初始化:置LC为空表,设置变量i, j,初值为1,分别指向LA和LB的第一个DE, k表示LC的长度,初值为0.
②当i<=LENGTH(LA) AND j<=LENGTH(LB)时,判断:若i所指的元素<=j所指的元素,则将i所指的元素插入在LC的k+1前,并且i, k的值分别加1;
否则,将j所指的元素插入在LC的k+1前,并且j,k的值分别加1。
③重复②直到某个表的元素插入完毕。
④将未插入完的表的余下的元素,依次插入在LC后。
void merge_list(LA,LB,LC){
Initiate(LC);//初始化线性表LC
int i=1;j=1;k=0;//初始化位序值
while((i<=length(LA))&&(j<=length(LB))) //分别指向LA和LB位序为1的元素
{
if(Get(LA,i)<=Get(LB,j)) //当LA的第i个元素<LB的第j个元素时
Insert(LC,k+1,Get(LA,i)),k++,i++; //把LA的第i个元素插入到LC末尾,并且位序+1
else
Insert(LC,k+1,Get(LB,i)),k++,j++; //把LB的第j个元素插入到LC末尾,并且位序+1
}
while(i<=length(LA)) //若LA的位序数小于LA数组总长
{
Insert(LC,k+1,Get(LA,i)),k++,i++; //将LA的元素,插入到LC末尾,位序+1
}
while(i<=length(LB)) //若LB的位序数小于LB数组总长
{
Insert(LC,k+1,Get(LB,j)),k++,j++; //将LB的元素,插入到LC末尾,位序+1
}
}
2.2 线性表顺序存储结构
用一组地址连续的存储单元依次存储线性表的元素。
设线性表的每个元素占用k个存储单元,则第i个元素ai的存储位置为: Loc(ai)- Loc(ai)+(i-1)*k其中, Loc(ai)为线性表的起址。
2.2 线性表链式存储结构
用一组任意的存储单元(不要求地址连续)来存储线性表的元素。每个元素对应一组存储单元(称为结点)。
每个结点包括两个域:存储数据元素信息的数据域和存储直接后继所在位置的指针域。
N个结点通过指针域组成的表,称为线性链表(单链表)。
单链表中每个操作的单独实现
--------------------定义结点 -------------------
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int ElemType;
typedef struct Node
{
ElemType data; //数据域
struct Node *next; //指针域
}Node;
typedef struct Node *Linklist;
---------------------链表初始化 ----------------------
int Create(Linklist *L)
{
*L=(Linklist)malloc(sizeof(Node));
//创建了一个结点,并且用L指向了这个结点
if(!(*L))
return ERROR;
(*L)->next=NULL;
return OK;
}
--------------------求长度函数 -----------------------
int Length(Linklist L)
{
int i=0;
Linklist p;
p=L->next; //指向的第一个结点
while(p)
{
i++;
p=p->next; //指向下一个结点
}
return i;
}
---------------------取元素操作-----------------------
int Get(Linklist L,int i)//ElemType *e)
{
int j;
Linklist p;
p=L->next;
j=1;
while(p && j<i)
{
j++;
p=p->next;
}
if (!p|| j>i)
return ERROR;
//*e= p->data;
return p->data;
}
---------------------定位元素-------------------------
int Locate(Linklist L,ElemType e)
{
int i=1;
Linklist p;
p=L->next;
while(p)
{
if (p->data==e)
return i;
p=p->next;
i++;
}
return ERROR;
}
---------------------前插元素-------------------------
int Insert(Linklist *L,int i,ElemType e)
{
int j;
Linklist p,s;
p= *L;
j=1;
while(p && j<i)
{
p=p->next;
j++;
}
if(!p|| j>i)
return ERROR;
s=(Linklist)malloc(sizeof(Node));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
---------------------删除元素-------------------------
int Delete(Linklist *L,int i)
{
int j;
Linklist p,q;
p= *L;
j=1;
while(p->next && j<i)
{
p=p->next;
j++;
}
if(!(p->next)||j>i)
return ERROR;
q=p->next;
p->next=q->next;
free(q);
return OK;
}
---------------------判空操作-------------------------
int Check(Linklist *L)
{
Linklist p;
p=*L;
if(p->next)//头指针是否为空?
printf("链表非空!\n");
return OK;
}
---------------------清空表操作-----------------------
int Clear(Linklist *L)
{
Linklist p;
p =*L;
while(p->next)
{
p=p->next;
p->data=0;//只是数据清零,并非释放内存
}
return OK;
}
执行后:
这就是关于线性表的一些基本操作。