您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习——线性表

2017-10-27 17:14 141 查看

一、定义:

线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。

在稍复杂的线性表中,一个数据元素可由多个数据项(item)组成,此种情况下常把数据元素称为记录(record),含有大量记录的线性表又称文件(file)。

线性表中的个数n定义为线性表的长度,n=0时称为空表。在非空表中每个数据元素都有一个确定的位置,如用ai表示数据元素,则i称为数据元素ai在线性表中的位序。

线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…,n时,ai有且仅有一个直接前驱

二、线性表的抽象数据类型:

#include <studio.h>
/*
操作方法:
InitList(*L):初始化操作,建立一个空的线性表
ListEmpty(L):若线性表为空,返回True,否则返回False
ClearList(*L):将线性表清空。
GetElem(L,i,e):将线性表L中的第i个位置元素赋值给e
LocateElem(L,e):在线性表L中查找与给定值e相等的元素,如果查找成功
返回该元素在表中序号表示成功,否则,返回0表示失败
ListInsert(*L,i,e):在线性表L中的i个位置插入新元素e
ListDelete(*L,i,*e):删除线性表L中地i个位置元素,并用e返回其值
ListLength(L):返回线性表L的元素个数
*/
void union(List *La,List Lb)//union在这里只是个名字
{
int La_len,Lb_len,i;
ElemType e;/*声明一个与La和Lb相同的数据元素e*/
La_len=ListLength(La);//求线性表的长度
Lb_len=ListLength(Lb);//求线性表的长度
for(i=1;i<Lb_len;i++)//循环遍历Lb的长度
{
GetElem(Lb,i,e); //取出第i个数据元素把它赋值给e
if(!LocateElem(La,e,equal))//如果La不存在和e相同的元
ListInsert(La,++La_len,e);//就向线性表的长度里面插入新元素e
}
}


三、顺序储存方式:

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。

线性表顺序存储的结构代码:

#define MAXLENGTH 20

struct sequencelist
{
int data[MAXLENGTH];
int length;
};


data数组为这个线性表的主要部分,数据元素就存在于此数组中,而对这个线性表的操作都是基于这个数组.

线性表的最大容量为:MAXLENGTH。

length是这个线性表的一个属性,表示这个线性表包含当前元素的个数。

四、地址计算方法:

储存器中的每个储存单元都有自己的编号,这个编号称为地址

假如每个数据元素的类型在储存单元中占c个储存单元,那么线性表中第i+1个数据元素的储存位置和第i个数据元素的储存位置满足下列关系(LOC表示获得储存位置的函数):

LOC(a i+1) = LOC(a i)+ c


五、六、七、顺序储存结构的插入和删除

1.线性表的取元素操作

用索引值查找元素的值。

//get list elements
//make sure elemet is NOT NULL when calling.
int getElement(struct sequencelist list,int index,int *element)
{
printf("\ngetElement\n");
int length = list.length;
printf("length is %d\n",length);
if(length ==0 || index < 0 || index >= length)
return ERROR;
*element = list.data[index];
return OK;
}


2.线性表的插入操作



(1)如果插入位置不合理,抛出异常;

(2)如果线性表长度大于等于数组长度,则抛出异常或者动态增加容量;

(3)从最后一个元素遍历到第i个位置,分别将它们后移一个位置;

(4)将要插入元素填入位置i处;

(5)表长加1;

3.线性表的删除操作

类似增的相反操作。

// Delete opration
int delete(struct sequencelist *list,int index)
{
int length = list->length;
if(length ==0 || index < 0 || index > length-1 )
return ERROR;
for(int i = index;i<length-1;i++)
{
list->data[i] = list->data[i+1];
}
list->data[length-1] = '\0';//delete the last element.
list->length--;
return OK;
}


八、九、单链表如何进行整表创建和删除?

1.整表创建:

声明一个结点p和计数器变量i;

(1)初始化一个空链表L;

(2)让L的头结点的指针指向NULL,即建立一个带头结点的单链表;

循环:

(3)生成一新结点赋值给p;

(4)随机生成一数字赋值给p指针的数据域p->data=rand();

(5)将p结点插入到头结点与前一新结点之间。

实现代码如下:

/*随机产生n个元素的值,建立带头结点的单链表L(头插法)*/
void CreatListHead(LinkList *L,int n)
{
LinkList p;
int i;
srand(time(0));    /*初始化随机数种子*/
*L=(LinkList)malloc(sizeof(Node));
(*L)->next=NULL;   /*先建立一个带头结点的单链表*/
for(i=0;i<n;i++)
{
p=(LinkList)mallloc(sizeof(Node));  /*生成新结点*/
p->data=rand()%100+1;
p->next=(*L)->next;
(*L)->next=p;   /*插入到表头*/
}

}


注:for循环中要不断使用malloc函数开辟新的空间

2.整表删除

单链表整表删除的思路如下:

(1)声明一结点p和q;

(2)将第一个结点赋值给p;

循环:

(3)将下一结点赋值给q;

释放p;

(4)将q赋值给p。

实现
a303
代码算法如下:

/*初始条件:顺序线性表L已存在,操作结果:将L重置为空表*/
Status CLearList(LinkList *L)
{
LinkList p,q;
p=(*L)->next;
while(p)           /*没到表尾*/
{
q=p->next;
free(p);
p=q;
}
(*L)->next=NULL;   /*头结点指针域为空*/
return OK;
}


十、什么是循环列表?什么是双向链表?

由于单链表不能回到之前的结点,所以就将最后一个结点中指针域中的指针由NULL改为指向头结点的指针。

在循环链表的基础上,如果要遍历到前面的一个结点时,所需的时间复杂度为o(n),所以为了方便,在每一个结点中再新增一个指向前面一个结点的指针域。即为双向链表。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: