线性表之顺序表(一)

6 篇文章 0 订阅
4 篇文章 0 订阅

在这里我们将介绍线性表的顺序存储结构–顺序表。这里我们介绍两种类型的顺序表,一种是静态的顺序表,另一种是动态增长的顺序表;并使用C和C++两种语言进行描述。这里给出C语言实现的具体的代码和说明,而C++的实现只是简单贴代码,不再详细说明。

一、相关概念
1.顺序表的概念
线性表的顺序存储结构称为顺序表(sequential list).
2.特点
(1)顺序表是用一段地址连续的存储单元一次存储线性表的数据元素;
(2)相邻元素不仅逻辑上相邻,而且在物理内存上也是相邻的;
(3)顺序表的元素可以随机存取(访问)
(4)插入和删除比较麻烦,需要大量移动元素
二、静态顺序表
1.结构体定义(C语言描述)
顺序表和数组本质上一样的,只不过比数组多了一个记录有效元素个数的变量,其他特点基本都一样,比如说随机访问等。
#define SIZE 10 //静态顺序表最大的元素个数上限
typedef struct Seqlist
{
    int iElem_a[SIZE]; //顺序表总空间
    int iLength_st;//表中有效元素个数
}Seqlist;
2.顺序表操作
我们将顺序表操作的函数的声明写在Seqlist.h文件中:
#ifndef SEQLIST_H_      //防止头文件被重复包含
#define SEQLIST_H_

#define SIZE 10
typedef struct Sqlist
{
    int iElem_a[SIZE];
    int iLength_st;
}Sqlist;

void InitSeqlist(Sqlist *pList);    //顺序表初始化
bool Insert(Sqlist *pList, int iPos, int iVal);//插入
bool DeleteByPos(Sqlist *pList, int iPos);//删除
void Destroy(Sqlist *pList);//销毁顺序表,在静态顺序表中没实质性作用
void Clear(Sqlist *pList);//清空顺序表
bool IsEmpty(Sqlist *pList);//顺序表为空返回true
bool IsFull(Sqlist *pList);//顺序表满返回true
int  GetLength(Sqlist *pList);//获取顺序表有效元素个数
bool GetValByPos(Sqlist *pList, int iPos, int *iRetVal);//获取指定位置元素
void PrintSqlist(Sqlist *pList);//输出顺序表
#endif

下面在Seqlist.c文件中给出顺序表操作的具体实现:

#include <stdio.h>
#include <stdlib.h>
#include "Seqlist.h"



int main(void)
{
    Sqlist list;
    InitSeqlist(&list);
    for (int i = 0; i < 12; ++i)
    {
        Insert(&list, 0, i);
    }
    PrintSqlist(&list);
    Insert(&list, 10, 10);
    PrintSqlist(&list);

    /*for (int i = 0; i < 12; ++i)
    {
        DeleteByPos(&list, 0);
        PrintSqlist(&list);
    }
    PrintSqlist(&list);*/
    for (int i = 0; i < 12; ++i)
    {
        int iRt;
        GetValByPos(&list, i, &iRt);
        printf("%5d\n", iRt);
    }
    printf("\n");
    return 0;
}

//初始化顺序表,注意异常情况检查
void InitSeqlist(Sqlist *pList)
{
    if (NULL == pList)  //确保链表存在
    {
        printf("The Seqlist isn't exist!!!\n");
        return;
    }
    pList->iLength_st = 0;
}

//插入元素,先判断是否顺序表已满,然后再判断插入位置是否正确,移动元素插入
bool Insert(Sqlist *pList, int iPos, int iVal)
{
    //顺序表存在而且没有满
    if (pList == NULL)
    {
        printf("The Sqlist isn't exist!!!\n"); 
        return false;
    }
    if (IsFull(pList))
    {
        printf("The Sqlist is full!\n");
        return false;
    }
    //插入位置是否合法
    if (iPos > pList->iLength_st || iPos < 0)
    {
        printf("The Insert positon is valid.\n");  
        return false;
    }
    //移动元素   
    for (int iIndex = pList->iLength_st - 1; iIndex >= iPos; --iIndex)
    {
        pList->iElem_a[iIndex + 1] = pList->iElem_a[iIndex];
    }
    //放入
    pList->iElem_a[iPos] = iVal;
    pList->iLength_st += 1;
    return true;
}

//删除指定位置的元素,找到删除的元素的位置后,直接移动元素进行覆盖,记得改变顺序表有效元素的个数
bool DeleteByPos(Sqlist *pList, int iPos)
{
    if (NULL == pList)
    {
        printf("The seqlist isn't exist!!!\n");
        return false;
    }
    if (IsEmpty(pList))
    {
        //printf("The seqlist is empty!!!\n");
        return false;
    }
    if (iPos < 0 || iPos > pList->iLength_st - 1)
    {
        printf("The insert position is valid!!!\n");
        return false;
    }
    for (int iIndex = iPos; iIndex < pList->iLength_st - 1; ++iIndex)
    {
        pList->iElem_a[iIndex] = pList->iElem_a[iIndex + 1];
    }
    --pList->iLength_st;
    return true;
}

//销毁顺序表,因为这里是静态顺序表,所以这个函数没有实质性的作用
void Destroy(Sqlist *pList)
{
    Clear(pList);
}

//清空顺序表,直接将记录顺序表有效元素个数的变量置为0
void Clear(Sqlist *pList)
{
    if (NULL == pList)
    {
        printf("The seqlist isn't exist\n");
        return;
    }
    pList->iLength_st = 0;
}

//判断顺序表是否为空
bool IsEmpty(Sqlist *pList)
{
    if (NULL == pList)
    {
        printf("The Seqlist isn't exist!!!\n");
        return false;
    }
    return 0 == pList->iLength_st;
}

//判断顺序表是否已满
bool IsFull(Sqlist *pList)
{
    if (NULL == pList)
    {
        printf("The Seqlist isn't exist!!!\n");
        return false;
    }
    return SIZE == pList->iLength_st;
}

//获取顺序表有效元素的个数
int  GetLength(Sqlist *pList)
{
    if (NULL == pList)
    {
        printf("The seqlist isn't exist.\n");
        return -1;
    }
    return pList->iLength_st;
}

//获取顺序表中iPos位置元素的值
bool GetValByPos(Sqlist *pList, int iPos, int *iRetVal)
{
    if (NULL == pList)
    {
        printf("The seqlist isn't exist.\n");
        return false;
    }
    if (iPos < 0 || iPos >= pList->iLength_st)
    {
        printf("The position is valid\n");
        return false;
    }

    *iRetVal = pList->iElem_a[iPos];
    return true;
}

//打印顺序表中的元素
void PrintSqlist(Sqlist *pList)
{
    if (NULL == pList || pList->iLength_st == 0)
    {
        return;
    }

    for (int iCount = 0; iCount < pList->iLength_st; ++iCount)
    {
        printf("%5d", pList->iElem_a[iCount]);
    }
    printf("\n");
}
三、动态顺序表
动态顺序表和静态顺序表的区别在于动态顺序表可以动态进行增长,而静态顺序表的最大容量是在程序运行前已经写好的,无法改变。
1.结构体定义(C语言描述)
#define INIT_SIZE 10    //初始化顺序表大小
#define INC_SIZE 10     //顺序表的分配增量
typedef struct DSqlist
{
    int *iElem_st;  //存储空间基址
    int iLength_st; //当前长度
    int iSize_st;   //当前分配的存储容量
}DSqlist;
2.动态顺序表操作
动态增长的顺序表和静态顺序表的操作大部分相同,主要不同在于两个地方。一个是当顺序表满时,动态顺序表可以再增长从而插入元素,而静态顺序表则无法再插入元素;二是在销毁顺序表时两者不一样。
我们将顺序表操作的函数的声明写在DynamicSeqlist.h文件中:
#ifndef DYNAMICSEQLIST_H_
#define DYNAMICSEQLIST_H_

#define INIT_SIZE 10    //初始化顺序表大小
#define INC_SIZE 10     //顺序表的分配增量
typedef struct DSqlist
{
    int *iElem_st;  //存储空间基址
    int iLength_st; //当前长度
    int iSize_st;   //当前分配的存储容量
}DSqlist;

bool IsExist(DSqlist *pList);   //判断顺序表是否存在
void InitDSeqlist(DSqlist *pList);  //初始化
bool Insert(DSqlist *pList, int iPos, int iVal);//插入
bool DeleteByPos(DSqlist *pList, int iPos); //删除
void Destroy(DSqlist *pList);   //销毁
void Clear(DSqlist *pList);     //清空
bool IsEmpty(DSqlist *pList);   //判断是否为空
bool IsFull(DSqlist *pList);    //判断是否为满
int  GetLength(DSqlist *pList); //获取有效元素个数
bool GetValByPos(DSqlist *pList, int iPos, int *iRetVal); //获取指定位置元素的值
void PrintSqlist(DSqlist *pList); //打印元素
bool Resize(DSqlist *pList);    //重新分配内存空间
#endif
下面在DynamicSeqlist.c文件中给出在以上操作的具体C语言代码实现:
#include"DynamicSeqlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    DSqlist list;
    InitDSeqlist(&list);
    for (int i = 0; i < 15; ++i)
    {
        Insert(&list, 0, i);
    }
    PrintSqlist(&list);
    printf("%5d\n", list.iSize_st);
    for (int i = 0; i < 15; ++i)
    {
        DeleteByPos(&list, 0);
        PrintSqlist(&list);
    }

    PrintSqlist(&list);
    return 0;
}

bool IsExist(DSqlist *pList)
{
    return pList != NULL;
}

void InitDSeqlist(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return;
    }
    pList->iElem_st = (int*)malloc(sizeof(int) * INIT_SIZE);
    if (NULL == pList->iElem_st)
    {
        printf("Alloc the memory is failed.\n");
        return;
    }
    pList->iSize_st = INIT_SIZE;
    pList->iLength_st = 0;
}

bool Insert(DSqlist *pList, int iPos, int iVal)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }
    if (IsFull(pList))
    {
        Resize(pList);
    }
    if (iPos < 0 || iPos > pList->iLength_st)
    {
        printf("The insert position is valid.\n");
        return false;
    }

    for (int iIndex = pList->iLength_st - 1; iIndex >= iPos; --iIndex)
    {
        pList->iElem_st[iIndex + 1] = pList->iElem_st[iIndex];
    }
    pList->iElem_st[iPos] = iVal;   
    pList->iLength_st++;
    return true;
}

bool DeleteByPos(DSqlist *pList, int iPos)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }
    if (IsEmpty(pList))
    {
        printf("The seqlist is empty.\n");
        return false;
    }

    if (iPos < 0 || iPos >= pList->iLength_st)
    {
        printf("The delete position is valid.\n");
        return false;
    }

    for (int iIndex = iPos; iIndex < pList->iLength_st - 1; ++iIndex)
    {
        pList->iElem_st[iIndex] = pList->iElem_st[iIndex + 1];
    }
    pList->iLength_st--;
    return true;
}

void Destroy(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return;
    }
    free(pList->iElem_st);
    pList->iLength_st = 0;
    pList->iSize_st = 0;
    pList->iElem_st = NULL;
}

void Clear(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return;
    }
    pList->iLength_st = 0;
}

bool IsEmpty(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }
    return (pList->iLength_st == 0);
}

bool IsFull(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }
    return (pList->iLength_st == pList->iSize_st);
}

int  GetLength(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return -1;
    }

    return pList->iLength_st;
}

bool GetValByPos(DSqlist *pList, int iPos, int *iRetVal)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }
    if (iPos < 0 || iPos >= pList->iLength_st)
    {
        printf("The posiont is valid.\n");
        return false;
    }
    *iRetVal = pList->iElem_st[iPos];
    return true;
}

void PrintSqlist(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return;
    }
    for (int iIndex = 0; iIndex < pList->iLength_st; ++iIndex)
    {
        printf("%5d", pList->iElem_st[iIndex]);
    }
    printf("\n");
}

bool  Resize(DSqlist *pList)
{
    if (!IsExist(pList))
    {
        printf("The dynamic seqlist isn't exist.\n");
        return false;
    }

    int *pTemp = pList->iElem_st;
    pList->iElem_st = (int*)malloc(sizeof(int)*(pList->iSize_st + INC_SIZE));   
    if (NULL != pList->iElem_st)
    {
        memcpy(pList->iElem_st, pTemp, sizeof(int) * pList->iSize_st);
        pList->iSize_st += INC_SIZE;
        free(pTemp);
        pTemp = NULL;
        return true;
    }
    else
    {
        return false;
    }
}

下面直接给出使用C++实现顺序表的代码:
//CppSeqlist.h头文件

#pragma once
const int SIZE = 10;

class CSeqList
{
public:
    CSeqList();
    ~CSeqList();
    int Length();
    bool Get(int i, int &iRtVal);
    int Locate(int x);
    void Insert(int i, int x);
    void Detele(int i);
    void PrintList();
private:
    int _iData_a[SIZE];     //存放数据元素的数组
    int _iLength;           //线性表的长度
};

//CppSeqlist.cpp
#include "CppSeqlist.h"
#include <iostream>
using namespace std;

CSeqList::CSeqList()
{
    _iLength = 0;
}

CSeqList::~CSeqList()
{

}

int CSeqList::Length()
{
    return _iLength;
}

bool CSeqList::Get(int i, int &iRtVal)
{
    if (i < 0 || i > _iLength - 1)
    {
        cout << "the position is valid.\n" << endl;
        return false;
    }
    iRtVal = _iData_a[i];
    return true;
}

void CSeqList::Insert(int i, int x)
{
    if (_iLength == SIZE)
    {
        cout << "The seqlist is full." << endl;
        return;
    }
    if (i < 0 || i > _iLength)
    {
        cout << "the position is valid." << endl;
        return;
    }
    for (int iIndex = _iLength - 1; iIndex >= i; --iIndex)
    {
        _iData_a[iIndex + 1] = _iData_a[iIndex];
    }
    _iData_a[i] = x;
    ++_iLength;
}

void CSeqList::Detele(int i)
{
    if (i < 0 || i > _iLength - 1)
    {
        cout << "The position is valid." << endl;
        return;
    }
    for (int iIndex = i; iIndex < _iLength - 1; ++iIndex)
    {
        _iData_a[iIndex] = _iData_a[iIndex + 1];
    }
    --_iLength;
}

void CSeqList::PrintList()
{
    for (int iIndex = 0; iIndex < _iLength; ++iIndex)
    {
        cout << _iData_a[iIndex] << "   ";
    }
    cout << endl;
}

int main(void)
{
    CSeqList list;
    for (int i = 0; i < 12; ++i)
    {
        list.Insert(0, i);
    }
    list.PrintList();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值