顺序表及其多种实现方式 --- C/C++

所谓顺序表,即线性表的顺序存储结构。下面给出的是数据结构---线性表的定义。

ADT List{

  数据对象:

    线性表的数据对象的集合为{a1,a2,a3,...,an},每个元素的类型为ElemType。

  数据关系:

    除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每个元素有且仅有一个直接后继元素。

    数据元素之间的关系是一对一的关系。

  基础操作:

    InitList(&L);  //构造一个空的线性表

    DestroyList(&L); //销毁线性表

    ClearList(&L); //清空线性表

    ListEmpty(L); //若线性表为空,返回true,否则返回false

    ListLength(L);//求表长

    GetElem(L, i, &e); //将线性表中第i个元素赋值给e

    LocateElem(L, e, cmp()); //返回L中第一个满足cmp()函数的元素的序号,若不存在,则返回0

    ListInsert(&L, i, e); //在L中的第i个位置之前插入元素e且L的长度+1

    ListDelete(&L, i, &e); //删除L中的第i个元素并用e返回其值,且L的长度-1

    ListTraverse(L, visit()); //线性表的遍历,依次对每个元素调用visit函数

  其他操作:

    PrioElem(L, cur_e, &pre_e); //cue_e是L中的数据元素,用pre_e返回其前驱;若无前驱则操作失败

    NextElem(L, cue_e, &next_e); //cur_e是L中的数据元素,用next_e返回后继;若无后继则操作失败

    union(&L1, &L2); //求二者元素并集;又可根据线性表是否有序有不同的操作。

}

以下是线性表的顺序存储结构的多种实现方式,详细参阅代码。(大部分只实现了基础操作)

1.用C语言实现顺序表 静态数组方式

/************************************************************************
    用C语言实现顺序表 静态数组方式
************************************************************************/
#include <cstdio>

typedef int ElemType;
typedef int Status;

const int ERROR = 0;
const int OK = 1;
const int TRUE = 1;
const int FALSE = 0;
const int LIST_SIZE = 100;

//定义顺序表结构ADT
typedef struct{
    int elem[LIST_SIZE];
    int length;
}SqList, *pList;

//初始化顺序表
Status InitList(pList List)
{
    List->length = 0;
    return OK;
}

//释放顺序表
Status DestroyList(pList List)
{
    List->length = 0;
    return OK;
}

//判断顺序表是否为空 是 返回 1 否则 返回 0
Status ListEmpty(pList List)
{
    if (List->length)
        return FALSE;
    return TRUE;
}

//返回顺序表的长度
int ListLength(pList List)
{
    return List->length;
}

//根据下标获取元素
Status GetElem(pList List, int i, ElemType *e)
{
    if (i < 1 || i > List->length)
        return ERROR;
    //第i个数据元素存储在下标为i-1的数组中
    *e = List->elem[i - 1];
    return OK;
}

//判断给定数据是否为顺序表的元素
Status LocateElem(pList List, int e)
{
    if (ListEmpty(List))
        return ERROR;
    for (int i = 0; i < List->length; ++i)
    {
        if (e == List->elem[i])
            return TRUE;
    }
    return FALSE;
}

//返回元素的前驱
Status PriorElem(pList List, ElemType cur_e, ElemType *pre_e)
{
    if (0 == List->length)
        return ERROR;
    for (int i = 0; i < List->length; ++i)
    {
        if (cur_e == List->elem[i] && i != 0){
            *pre_e = List->elem[i - 1];
            return OK;
        }
    }
    return ERROR;

}

//返回元素cur_e的后驱
Status NextElem(pList List, ElemType cur_e, ElemType *next_e)
{
    if (0 == List->length)
        return ERROR;
    for (int i = 0; i < List->length - 1; ++i)
    {
        if (cur_e == List->elem[i]){
            *next_e = List->elem[i + 1];
            return OK;
        }
    }
    return ERROR;
}

//在数据元素i之前插入新元素
Status ListInsert(pList List, int i, ElemType e)
{
    if (i < 1 || i > List->length + 1)
        return ERROR;
    if (LIST_SIZE <= List->length)
        return ERROR;
    //q为插入位置,次位置及之后的要先移位才能在q这插入
    ElemType* q = &List->elem[i - 1];
    //移位
    for (ElemType *p = &List->elem[List->length - 1]; p >= q; --p)
        *(p + 1) = *p;
    *q = e;
    ++List->length;
    return OK;
}

//删除顺序表中的第i个数据元素,并用e返回
Status ListDelete(pList List, int i, ElemType *e)
{
    if (i < 1 || i > List->length)
        return ERROR;
    //p为需要删除的元素地址 讲后面的一层层移位就好 q为最后一位元素地址
    ElemType *p = &List->elem[i - 1];
    ElemType *q = &List->elem[List->length - 1];
    *e = *p;
    //移位
    while (p < q){
        *p = *(p + 1);
        ++p;
    }
    --List->length;
    return OK;
}

//线性表的遍历
Status ListTraverse(pList List, void(*visit)(ElemType elem))
{
    if (ListEmpty(List))
        return ERROR;
    for (int i = 0; i < List->length; ++i)
        visit(List->elem[i]);
    return OK;
}

void visit(ElemType e){
    printf("%4d", e);
}

int main()
{
#ifdef _LOCAL
    freopen("input.txt", "r", stdin);
#endif
    SqList MyList;
    pList List = &MyList;

    InitList(List);
    ElemType tmp;
    for (int i = 1; i <= 5; ++i)
    {
        scanf("%d", &tmp);
        if (!ListInsert(List, i, tmp)){
            printf("ListInsert Error!\n");
        }
    }

    //if (!ListDelete(List, 5, &tmp)){
    //    printf("ListDelete Error!\n");
    //}
    //else{
    //    printf("Delete %d\n", tmp);
    //}

    ListTraverse(List, visit); printf("\n");

    return 0;
}

2.C语言实现顺序表,内存动态分配方式

/************************************************************************
    C语言实现顺序表,内存动态分配方式
************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define LIST_INIT_SIZE 15
#define ADD_SIZE 10
#define OVERFLOW -2

typedef int ElemType;
typedef int Status;

typedef struct{
    int *elem;
    int length;    //线性表当前长度
    int listsize;    //顺序表已分配空间
}SqList, *pList;

//创建一个顺序表
Status InitList(pList List){
    List->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if (!List->elem)
        exit(OVERFLOW);
    List->length = 0;
    List->listsize = LIST_INIT_SIZE;
    return OK;
}

//销毁该顺序表
Status DestroyList(pList List){
    if (List->elem){
        free(List->elem);
        List->elem = NULL;
        return OK;
    }
    else{
        return ERROR;
    }
}

//判断顺序表是否为空
Status ListEmpty(pList List){
    if (List){
        return !List->length;
    }
    return ERROR;
}

//清空顺序表
Status ClearList(pList List){
    if (List){
        List->length = 0;
        return OK;
    }
    else{
        return ERROR;
    }
}

//返回顺序表元素个数
Status ListLength(pList List){
    if (List){
        return List->length;
    }
    else{
        return ERROR;
    }
}

//获取元素i
Status GetElem(pList List, int i, ElemType *e){
    if (List){
        if (i < 1 || i > List->length)
            return ERROR;
        *e = List->elem[i - 1];
        return OK;
    }
    else{
        return ERROR;
    }
}

//返回元素e的下标
Status LocateElem(pList List, ElemType e){
    if (List){
        for (int i = 0; i < List->length; ++i)
        {
            if (e == List->elem[i])
                return i + 1;
        }
        return 0;
    }
    else{
        return ERROR;
    }
}

//i之前插入元素
Status ListInsert(pList List, int i, ElemType e){
    if (List){
        //插入位置出错,报错
        if (i < 1 || i > List->length + 1){
            return ERROR;
        }
        //空间已满,重新分配
        if (List->length >= List->listsize){
            //重新分配空间
            ElemType *newbase = (ElemType*)realloc(List->elem, (List->listsize + ADD_SIZE)*sizeof(ElemType));
printf("Realloc!\n");
            if (!newbase){
                exit(OVERFLOW);
            }
            //将重新分配的空间赋给线性表中的指针
            List->elem = newbase;
            //更新当前已分配的空间
            List->listsize += ADD_SIZE;
        }
        //利用指针p、q移位,p指向尾元素的后一位,q指向目标地址
        ElemType *p = &List->elem[List->length];
        ElemType *q = &List->elem[i - 1];
        while (p > q){
            *p = *(p - 1);
            --p;
        }
        *q = e;
        ++List->length;
        return OK;
    }
    else
    {
        return ERROR;
    }
}

//删除i处元素
Status ListDelete(pList List, int i, ElemType *e){
    if (List){
        if (i < 1 || i > List->length){
            return ERROR;
        }
        ElemType *p = &List->elem[i - 1];
        ElemType *q = &List->elem[List->length-1];
        while (p < q){
            *p = *(p + 1);
            ++p;
        }
        --List->length;
        return OK;
    }
    else{
        return ERROR;
    }
}

Status ListPrint(pList List)
{
    if (List){
        for (int i = 0; i < List->length; ++i)
            printf(i ? " %d" : "%d", List->elem[i]);
        return OK;
    }
    else{
        printf("Empty List!");
        return ERROR;
    }
}

int main()
{
    SqList MyList;
    pList pMyList = &MyList;
    InitList(pMyList);
    for (int i = 1; i <= 10; ++i)
        ListInsert(pMyList, i, i);

    ListPrint(pMyList);

    return 0;
}

3.用C++实现顺序表 静态数组方式 面向对象

/************************************************************************
    用C++实现顺序表 静态数组方式 面向对象
************************************************************************/
#include <cstdio>

const bool OK = 1;
const bool ERROR = 0;
const bool TRUE = 1;
const bool FALSE = 0;
const int LIST_SIZE = 100;

typedef int ElemType;
typedef int Status;

class SqList{
private:
    ElemType elem[LIST_SIZE];
    int length;
public:
    SqList();    //默认构造函数
    ~SqList();    //析构函数
    Status ListEmpty();    //判断顺序表是否为空
    int ListLength();    //获取顺序表的长度
    Status GetElem(int i, ElemType& e);    //获取第i个元素
    Status LocateElem(int e);    //e为顺序表中的元素,返回e的下标,0表示失败
    Status ListInsert(int i, ElemType e);    //在第i个元素之前插入e并是length加1
    Status ListDelete(int i, ElemType &e);    //删除顺序表的第i个元素
    Status ListTraverse(void (*visit)(ElemType &e));    //输出该顺序表
};

void visit(ElemType& e){
    printf("%4d", e);
}

int main()
{
    SqList Test;
    ElemType tmp;

    for (int i = 1; i <= 5; ++i)
        Test.ListInsert(i, i);
    //Test.ListDelete(3, tmp);

    Test.ListTraverse(visit);
    putchar(10);

    return 0;
}

SqList::SqList(){
    this->length = 0;
}

SqList::~SqList(){
    this->length = 0;
}

Status SqList::ListEmpty(){
    return !length;
}

int SqList::ListLength(){
    return this->length;
}

Status SqList::GetElem(int i, int& e){
    if (i < 1 || i > length)
        return ERROR;
    e = elem[i - 1];
    return OK;
}

Status SqList::LocateElem(int e){
    for (int i = 0; i < length; ++i)
    {
        if (e == this->elem[i])
            return i + 1;
    }
    return ERROR;
}

Status SqList::ListInsert(int i, int e){
    if (i < 1 || i > this->length + 1)
        return ERROR;
    if (this->length >= LIST_SIZE)
        return ERROR;
    //先将i位置及之后的元素后移,推荐使用指针实现
    ElemType *q = &this->elem[i - 1];    //q为目标地址
    for (ElemType *p = &this->elem[this->length]; p > q; --p)
    {
        *p = *(p - 1);
    }
    *q = e;
    ++length;
    return OK;

}

Status SqList::ListDelete(int i, int &e){
    if (i < 1 || i > length)
        return ERROR;
    //从目标地址的后一个元素开始一个个往前移
    ElemType *p = &elem[i - 1];    //p为目标地址
    ElemType *q = &elem[length];//q为尾元素的地址
    while (p < q){
        *p = *(p + 1);
        ++p;
    }
    --length;
    return OK;
}

Status SqList::ListTraverse(void(*visit)(ElemType &e)){
    if (length){
        for (int i = 0; i < length; ++i)
            visit(elem[i]);
        return OK;
    }
    else{
        printf("Empty List!");
        return OK;
    }

}

4.用C++和模板实现顺序表

/************************************************************************
    用C++和模板实现顺序表
************************************************************************/
#include <cstdio>

const int MAX_SIZE = 100;
#define OK 1
#define ERROR 0
#define TRUE 1
//#define FALSE 0
#define OVERFLOW -1
typedef int Status;

template<typename ElemType>
class SqList{
    ElemType m_data[MAX_SIZE+1]; //为了排序查找方便,从1下标开始存储
    int m_length;
public:
    //默认构造函数,相当于InitList()
    SqList() :m_length(0){}
    //析构函数,相当于DestroyList(),但什么也不做
    ~SqList(){ }
    //清空顺序表
    void ClearList(){
        m_length = 0;
    }
    //判断线性表是否为空
    bool ListEmpty(){
        return !m_length;
    }
    //求表长
    int ListLength(){
        return m_length;
    }
    //取得顺序表中的第i个元素
    Status GetElem(int i, ElemType& e){
        if (i < 1 || i > m_length)
            return ERROR;
        e = m_data[i];
        return OK;
    }
    //返回L中第一个满足cmp()函数的元素的序号,若不存在,则返回0
    Status LocateElem(ElemType e, bool(*cmp)(ElemType, ElemType)){
        m_data[0] = e;
        int i = m_length;
        while (!cmp(e, m_data[i])){
            --i;
        }
        return i;
    }
    //在L中的第i个位置之前插入元素e且L的长度+1
    Status ListInsert(int i, ElemType e){
        if (i < 1 || i > m_length + 1 || m_length >= MAX_SIZE){
            return ERROR;
        }
        for (int k = m_length; k >= i; --k){
            m_data[k+1] = m_data[k];
        }
        m_data[i] = e;
        ++m_length;
        return OK;
    }
    //删除L中的第i个元素并用e返回其值,且L的长度-1
    Status ListDelete(int i, ElemType& e){
        if (i < 1 || i > m_length)
            return ERROR;
        for (int j = i; j < m_length; ++j){
            m_data[j] = m_data[j + 1];
        }
        --m_length;
        return OK;
    }
    //线性表的遍历,依次对每个元素调用visit函数
    Status ListTraverse(void(*visit)(ElemType e)){
        if (m_length == 0){
            printf("Empty SqList");
            return ERROR;
        }
        for (int i = 1; i <= m_length; ++i){
            visit(m_data[i]);
        }
        return OK;
    }
};

bool cmp(int a, int b){
    return a == b;
}

void visit(int a){
    printf("%3d", a);
}

int main()
{
#ifdef _LOCAL
    freopen("input.txt", "r", stdin);
#endif
    SqList<int> L;
    int n, tmp;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i){
        scanf("%d", &tmp);
        L.ListInsert(i, tmp);
    }
    L.ListDelete(3, tmp);

    L.ListTraverse(visit); printf("\n");

}

时间: 2024-08-02 10:49:32

顺序表及其多种实现方式 --- C/C++的相关文章

【数据结构】 线性表的顺序表

线性表是一种最为常用的数据结构,包括了一个数据的集合以及集合中各个数据之间的顺序关系.线性表从数据结构的分类上来说是一种顺序结构.在Python中的tuple,list等类型都属于线性表的一种. 从抽象数据类型的线性表来看,一个线性表应该具有以下这些操作(以伪代码的形式写出): ADT List: List(self) #表的构造操作,创建一个新表 is_empty(self) #判断一个表是不是空表 len(self) #返回表的长度 prepend(self,elem) #在表的开头加入一个

顺序表结构

在计算机中线性表可以采用两种方式来保存,一种是顺序存储结构,另一种是链式存储结构. 顺序存储结构的线性表称为顺序表,链式存储结构的线性表称为链表. 顺序表就是按照顺序存储方式存储的线性表,该线性表的结点按照逻辑次序依次存放在计算机的一组连续的存储单元中. 由于顺序表是依次存放的,只要知道了谈顺序表的首地址以及每个数据元素所占用的存储长度,很容易计算出任何一个数据元素(也就是数据结点)的位置. 假设顺序表中所有结点的类型相同,则每个结点所占用存储空间的大小亦相同,每个结点占用c个存储单元.其中第1

C++方式实现顺序表

SeqList.h #include<iostream> using namespace std; #define MAXSIZE 15 typedef int DataType; typedef struct { DataType seqList[MAXSIZE]; //通常用一位数组来描述顺序表的数据存储 int size; /*线性表长度*/ } SeqList;   SeqList *Init_SeqList(); //初始化顺序表   void PushBack(SeqList* s

&quot;数据结构翻转课堂&quot;答疑实录——顺序表

[说明] 本文是<数据结构>翻转课堂在线答疑的实录,由云班课的"答疑/讨论"功能中导出数据整理而成.. [重要提示] 下面的内容,按时间从后往前的顺序提供,请直接到文章末尾,倒着看更顺畅. [课程实践答疑实录] 焦梦真2015-09-20 11:19:20说 太难了 贺利坚2015-09-20 11:25:48答 练就将军本色之时到了.待回头看,江山本是如此多娇! 高露2015-09-19 15:14:50 用指针和线性表那一块... 王增亮2015-09-15 21:18

数据结构学习总结(1)线性表之顺序表

通过前面的学习知道,具有“一对一”逻辑关系的数据,最佳的存储方式是使用线性表.那么,什么是线性表呢? 线性表,全名为线性存储结构.使用线性表存储数据的方式可以这样理解,即“把所有数据用一根线儿串起来,再存储到物理空间中”. 采用线性表将其储存到物理空间中. 首先,用“一根线儿”把它们按照顺序“串”起来,如图 2 所示:                                                             图 2 数据的"线性"结构 图 2 中,左侧是“

顺序表添加与删除元素以及 php实现顺序表实例

对顺序表的操作,添加与删除元素. 增加元素 如下图所示  对顺序列表 Li [1328,693,2529,254]  添加一个元素 111 ,有三种方式: a)尾部端插入元素,时间复杂度O(1);    保证了原始顺序列表的顺序. b)非保序的加入元素(不常见),时间复杂度O(1);   打乱了原始顺序列表的顺序. c)保需的元素插入,时间复杂度O(n);    保证了原始顺序列表的顺序. 删除元素 如下图所示  对顺序列表 Li [1328,693,2529,254]  删除元素 ,有三种方式

线性表---顺序表

线性结构的特点是:在非空的有限集合中,只有唯一的第一个元素和唯一的最后一个元素.第一个元素没有直接前驱元素,最后一个没有直接的后继元素.其它元素都有唯一的前驱元素和唯一的后继元素. 线性表是一种最简单的线性结构.线性表可以用顺序存储结构和链式存储结构存储,可以在线性表的任意位置进行插入和输出操作. 要想将线性表在计算机上实现,必须把其逻辑结构转化为计算机可识别的存储结构.线性表的存储结构主要有两种:顺序存储结构和链式存储结构. 线性表的顺序表示与实现 线性表的顺序存储结构 线性表的顺序存储结构指

javascript数据结构之顺序表

关于线性表的概念这里就不赘述了,可以自行百度和查阅资料,线性表按照存储(物理)结构分为顺序存储和链式存储,每种存储方式的不同决定了它的实现代码是不同的: 顺序存储的特点就是在内存中选一块连续的地址空间,然后将线性表放入其中,这样做便于线性表的存取,但是不利于插入和删除,而且在事先无法确定线性表长度的前提下可能会造成内存浪费或溢出. 这篇我是用javascript来实现线性表中的顺序表. 下面上代码: 1 var orderList = function(){ 2 var items = [];

线性表—顺序表

引言(重点): 1.线性表的概述 2.线性表的抽象数据类型描述 3.线性表的实现方式 4.线性表的具体实现 5.每种具体实现的分析 1.什么是线性表?线性表(Linear List):由同类型元素构成有序序列的线性结构. 特征:1.表中元素个数称为线性表的长度2.线性表没有元素时,称为空表3.表起始位置称表头,表结束位置称为表尾4.在一个元素的前面的元素叫前驱元素,在一个元素后面的元素叫后继元素. 2.线性表的抽象数据类型描述 List MakeEmpty():初始化一个空线性表L;Elemen