数据结构学习——线性表

一、定义:

线性表(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。
实现代码算法如下:

/*初始条件:顺序线性表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),所以为了方便,在每一个结点中再新增一个指向前面一个结点的指针域。即为双向链表。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值