数据结构——线性表

鉴于个人在数据结构的学习中经常遗忘一些重要概念,因此决定在博客中写下自己数据结构的学习历程和心得。


1.线性表的定义
  • 线性表(Linear List)是最常用而且最简单的一种数据结构,一个线性表是n个元素的有限序列。表中元素的数据类型需要具体情况具体定义。
  • 假如线性表中的元素排列是( a1 , a2 , …… , an ),则对于元素ai( i > 1 && i < n ),必有ai-1作为前驱,ai+1作为后继。表头元素只有后继,表尾元素只有前驱。
2.线性表基本操作的实现

  • 由于线性表有两种存储结构,因此在这先写下操作名称,在后文不同的存储方式中再分别写下具体实现操作。
init_linearlist( &L );    //创建一个空线性表
init_destroylist( &L );   //释放线性表内存 

list_empty( L );    //判断线性表是否为空表,若为空表则返回false,否则返回true

list_length( L );    //求线性表的长度(即数据元素个数)
list_clear( &L );    //将线性表清空
list_element_locate( L , e , cmp );    //查找线性表中的元素,返回符合条件的元素的位序,其中cmp是数据元素判定函数,相当于条件
list_getelem( L , i );    //返回线性表中第i个元素的值

list_insert( &L , i , e );    //把数据元素e插入线性表的第i个位置

list_delete( &L , x );    //该函数有两种形式,一种是按元素位序删除,一种是按值删除。看需求决定是否返回元素值
list_prior( L . x );
list_next( L, x );    //返回表中某元素的前驱/后继。这里同样有两种形式,一种是按元素位序,另一种是按值返回

  • 线性表的顺序存储
typedef int ElementType;

typedef struct {
    ElementType *element;
    int length;
    int listsize;
}List;

void init_linearlist ( List &L ){
    cin >> L.listsize;
    element = new ElementType[L.listsize];    //需要在程序最后用释放
    L.length = 0;
}

接下来是线性表的基本操作

ElementType getelem( List L , int i ){
    return L.element[i-1];
}

ElementType list_element_locate( List L , int e ){
    for( int i = 0;i < L.length; i++ ){
        if(L.element[i] == e)return i;
    }
    return 0;
}

void list_insert( List &L , int i , int e ){
    int temp;
    L.element[L.length++] = e;
    for( int j = L.length;j > i;j-- ){
        temp = L.element[j];
        L.element[j] = L.element[j-1];
        L.element[j-1] = temp;
    }
}

void list_delete1( List &L , int x ){
    int temp;
    for ( int i = L.length;i > x;i-- ){
        temp = L.element[i];
        L.element[i] = L.element[i-1];
        L.element[i-1] = temp;
    }
    L.length--;
}

void list_delete2( List &L , int x ){
    int temp;
    for( int i = L.length;i > list_element_locate(L,x);i-- ){
        temp = L.element[i];
        L.element[i] = L.element[i-1];
        L.element[i-1] = temp;
    }
    L.length--;
}                                                       //这里给出了两种删除操作,第一种是按位序,第二种是按值删除

假设利用两个线性表来表示集合A和B,如何利用线性表的操作来得到一个新集合AB呢?

void list_union( List &La , List Lb ){
    for( int i = 0;i < Lb.length;i++ ){
        int elem = getelem(Lb,i);
        if(!list_element_locate(La,e))list_insert(La,++La.length,elem);
    }
}

线性表顺序存储的操作就写到这里,相信读者们都可以看出这种方式的缺点。上述代码中不少函数执行效率都直接与表长挂钩,例如插入删除等操作,倘若表长很大,但相应操作只能逐位进行。则函数list_insert和list_delete1的时间复杂度为O(L.length),但是list_delete2的时间复杂度为O( L.length^2 ),接下来讲述线性表的链式存储。

  • 线性表的链式存储
typedef int ElementType;

typedef struct Lnode {
    ElementType data;
    struct Lnode *next;
}*List;

void init_linearlist( List &L ){
    L = new List;
    L->next = NULL;
}

基本操作是对单链表进行遍历,修改节点。

ElementType getelem( List L , int i ){
    List p = L;int j = 0;
    while( p && j < i ){
        p = p->next; j++;
    }
    if( !p || j > i )return 0;  //不存在该元素
    return p->data;
}

ElementType list_insert( List &L , int i , ElementType e ){
    List p = L;int j = 0;
    while( p && j < i ){
        p = p->next; j++;
    }
    if( !p || j > i )return 0;  //i小于1或者大于表长
    insertNode = new List;
    insertNode->data = e;
    insertNode->next = p->next;
    p->next = insertNode;
}

ElementType list_delete( List &L , int i ){
    List p = L;int j = 0;
    while( p && j < i-1 ){
        p = p->next; j++;
    }
    if( !p || j > i-1 )return 0;  //同上
    List q = p->next; 
    p->next = q->next;
    delete q;
}
今天先写到这里,下次更新一元多项式的加法。

猜你喜欢

转载自blog.csdn.net/ArtoriasLee/article/details/80487284