【数据结构】Liner-List 线性表(更新时间:2016-04-06)

【数据结构】Liner-List 线性表(更新时间:2016-04-06)

趁着室友刚刚开始学习数据结构,赶紧配合着他的进度来写关于数据结构的相关内容
博文中的代码均使用C++语法,部分代码(主要是函数重载等)无法在C语言环境下编译

线性表 是最简单、最基本也是最常用的数据结构,它是以数组为基础定义的使得所需要的 元素存储空间 一一对应的一种数据结构,即每一个存储元素都对应于一个特定的存储位置。

常见的线性表是用数组来存储,也就是我们常说的顺序存储:

struct ListNode;                        //定义线性表表头节点
typedef ListNode* PtrToNode;            //定义线性表表头指针
typedef PtrToNode LinerList;            //重定义表头指针
typedef int ElementType;                //重定义数据类型
struct ListNode                         //数据结构描述
{       
    int capacity;                       //表的容量 
    int tail;                           //指向当前表的尾部
    ElementType* Element;               //数据域
};
const int MAX_CAP = 100;                //初始容量

示意图:

线性存储链表示意图

基础操作

初始化

将线性表初始化,通过指针操作,将表头地址传入初始化函数,并以指针的形式返回表头。初始化表的容量以及表的尾指针。

LinerList Initial( void )                                                           //表的初始化
{
    LinerList L = NULL;

    L = ( LinerList ) malloc ( sizeof(ListNode) );                                  //分配表头地址
    L->capacity = MAX_CAP;                                                          //初始化数值域空间
    L->tail = 0;                                                                    //表尾部指针指向表头
    L->Element = ( ElementType* ) malloc( L->capacity * sizeof( ElementType ) );    //分配数值域地址
    return L;                                                                       //返回表头
}
删除表

将整个线性表删除,表头置为空指针

void Delete( LinerList L )                                                          //表的删除
{
    if( L != NULL )
    {
        free( L->Element );                                                         //释放数值域空间
        free( L );                                                                  //释放表头
        L = NULL;                                                                   //表头置空
    }
}
扩充表

在我们向线性表中插入数据的时候,由于线性表的有限性,会出现线性表容量溢出的情况,在这种情况下,我们可以使用realloc函数来达到重新分配数值空间的目的。

LinerList Expansion( LinerList L )                                                  //表的扩容
{
    L->capacity++;                                                                  //容量扩充
    L->Element = ( ElementType* ) realloc ( L->Element, L->capacity * sizeof( ElementType ) );  //重分配数据空间
}
查找

对于线性表,我们经常需要查询其中是否存在某特定的元素。

int Find( const LinerList L, const ElementType X )                                  //查找元素
{
    int pos = 0;                                                                    //游标初始化

    while( L->Element[pos] != X && pos < L->tail )                                  //游标遍历搜索
        pos++;
    if( pos != L->tail )                                                            //如果找到返回pos
        return pos;
    else
        return 0;
}
插入元素

对于线性表的插入主要分为简单插入和定点插入两种(使用函数重载来进行插入类别的判断):
简单插入 是指直接在表的尾部插入元素,如果表已满,则对表进行扩容。

LinerList Insert( LinerList L, const ElementType X )                                //简单插入
{
    if( L->tail == L->capacity )                                                    //判断是否过载
        Expansion( L );                                                             //扩容
    L->Element[ L->tail++ ] = X;                                                    //插入
    return L;                                                                       //返回表头
}

定点插入 是指插入位置与表的容量和表尾的相对状况进行插入,当插入位置在表尾内,则插入元素,如果插入位置非法,则返回原表。

LinerList Insert( LinerList L, const ElementType X, const int Pos )                 //定点插入
{
    int p = L->tail;                                                                //游标指向表尾

    if( Pos > L->tail )                                                             //判断插入位置合法性
    {
        cout << "Wrong insert position!\n";
        return L;
    }
    if( L->tail == L->capacity )                                                    //判断是否过载
    {
        Expansion( L );
        L->tail++;
    }
    for( ; p > Pos; p-- )                                                           //将数值逐个后移
        L->Element[p+1] = L->Element[p];
    L->Element[p] = X;                                                              //插入
}
删除元素

在线性表的使用过程中,除了插入一些元素之外,我们还需要删除一些元素。删除顺序线性表的方法是使用后面的元素填充到前面的元素之中。插入也分为简单删除和定点删除。由于代码中的Element类型为int,故暂时无法使用函数重载来在同一个代码区实现。
简单删除 调用代码中的Find函数来查找所要删除的元素是否出现在表中,如果出现则删除。

LinerList Delete( LinerList L, const ElementType X )                                //简单删除
{
    int pos = Find( L, X );                                                         //游标初始化

    if( !pos )                                                                      //未找到指定元素
    {
        cout << X << " is not found in the LinerList!\n";
        return L;
    }
    else
    {
        L->tail--;                                                                  //尾表前移
        while( pos < L->tail )                                                      //元素逐个前移
            L->Element[pos] = L->Element[pos+1];
        return L;
    }
}

定点删除 同定点插入。

LinerList Delete( LinerList L, const int Pos )                                      //定点删除
{
    int p = Pos;

    if( Pos > L->tail || Pos < 0 )                                                  //判断是否越界
    {
        cout << "Wrong deletion postion!\n";
        return L;
    }
    L->tail--;                                                                      //尾标前移
    while( p < L->tail )                                                            //元素逐个前移
        L->Element[p] = L->Element[p+1];
    return L;
}
打印表

在使用线性表的时候我们会需要将表格打印出来,在这里简单示例用空格隔开每个元素。

void Print( const LinerList L )                                                     //打印表
{
    int pos = 0;                                                                    //游标初始化

    if( L == NULL )
    {
        cout << "Empty List!\n";
        return;
    }
    while( pos < L->tail )
    {
        cout << L->Element[pos] << ' ';                                             //打印元素并添加空格
        pos++;
    }
    cout << endl;                                                                   //输出换行
}

代码示例

注:其中的一个删除元素的函数被注释掉了,不体现实际功能

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;
/*********************************************************/
struct ListNode;                        //定义线性表表头节点
typedef ListNode* PtrToNode;            //定义线性表表头指针
typedef PtrToNode LinerList;            //重定义表头指针
typedef int ElementType;                //重定义数据类型
struct ListNode                         //数据结构描述
{       
    int capacity;                       //表的容量 
    int tail;                           //指向当前表的尾部
    ElementType* Element;               //数据域
};
const int MAX_CAP = 100;                //初始容量
/*********************************************************/
void        Delete( LinerList L );                                      //表的删除
LinerList   Initial( void );                                            //表的初始化
LinerList   Expansion( LinerList L );                                   //表的扩充
int         Find( const LinerList L, const ElementType X );             //查找元素
LinerList   Insert( LinerList L, const ElementType X );                 //简单插入
LinerList   Insert( LinerList L, const ElementType X, const int Pos );  //定点插入
LinerList   Delete( LinerList L, const ElementType X );                 //简单删除
LinerList   Delete( LinerList L, const int Pos );                       //定点删除
void        Print( const LinerList L );                                 //打印表
/*********************************************************/
int main()
{
    LinerList L;
    ElementType X;
    int i;

    L = Initial();
    for( i = 0; i < MAX_CAP-1; i++ )
        Insert( L, i );
    Insert( L, 99 );
    Insert( L, 100, 100 );
    Print( L );
    Insert( L, 101, 102 );
    Delete( L, 103 );
    Delete( L );
}
/*********************************************************/
void Delete( LinerList L )                                                          //表的删除
{
    free( L->Element );                                                             //释放表的数值域空间
    free( L );                                                                      //释放表头
    L = NULL;                                                                       //表头置空
}

LinerList Initial( void )                                                           //表的初始化
{
    LinerList L = NULL;

    L = ( LinerList ) malloc ( sizeof(ListNode) );                                  //分配表头地址
    L->capacity = MAX_CAP;                                                          //初始化数值域空间
    L->tail = 0;                                                                    //表尾部指针指向表头
    L->Element = ( ElementType* ) malloc( L->capacity * sizeof( ElementType ) );    //分配数值域地址
    return L;                                                                       //返回表头
}

LinerList Expansion( LinerList L )                                                  //表的扩容
{
    L->capacity++;                                                                  //容量扩充
    L->Element = ( ElementType* ) realloc ( L->Element, L->capacity * sizeof( ElementType ) );  //重分配数据空间
}

int Find( const LinerList L, const ElementType X )                                  //查找元素
{
    int pos = 0;                                                                    //游标初始化

    while( L->Element[pos] != X && pos < L->tail )                                  //游标遍历搜索
        pos++;
    if( pos != L->tail )                                                            //如果找到则返回pos
        return pos;
    else
        return 0;
}

LinerList Insert( LinerList L, const ElementType X )                                //简单插入
{
    if( L->tail == L->capacity )                                                    //判断是否过载
        Expansion( L );                                                             //扩容
    L->Element[ L->tail++ ] = X;                                                    //插入
    return L;                                                                       //返回表头
}

LinerList Insert( LinerList L, const ElementType X, const int Pos )                 //定点插入
{
    int p = L->tail;                                                                //游标指向表尾

    if( Pos > L->tail )                                                             //判断插入位置合法性
    {
        cout << "Wrong insert position!\n";
        return L;
    }
    if( L->tail == L->capacity )                                                    //判断是否过载
    {
        Expansion( L );
        L->tail++;
    }
    for( ; p > Pos; p-- )                                                           //将数值逐个后移
        L->Element[p+1] = L->Element[p];
    L->Element[p] = X;                                                              //插入
}

LinerList Delete( LinerList L, const ElementType X )                                //简单删除
{
    int pos = Find( L, X );                                                         //游标初始化

    if( !pos )                                                                      //未找到指定元素
    {
        cout << X << " is not found in the LinerList!\n";
        return L;
    }
    else
    {
        L->tail--;                                                                  //尾表前移
        while( pos < L->tail )                                                      //元素逐个前移
            L->Element[pos] = L->Element[pos+1];
        return L;
    }
}
/*
LinerList Delete( LinerList L, const int Pos )                                      //定点删除
{
    int p = Pos;

    if( Pos > L->tail || Pos < 0 )                                                  //判断是否越界
    {
        cout << "Wrong deletion postion!\n";
        return L;
    }
    L->tail--;                                                                      //尾标前移
    while( p < L->tail )                                                            //元素逐个前移
        L->Element[p] = L->Element[p+1];
    return L;
}
*/
void Print( const LinerList L )                                                     //打印表
{
    int pos = 0;                                                                    //游标初始化

    if( L == NULL )
    {
        cout << "Empty List!\n";
        return;
    }
    while( pos < L->tail )
    {
        cout << L->Element[pos] << ' ';                                             //打印元素并添加空格
        pos++;
    }
    cout << endl;                                                                   //输出换行
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值