数据结构--顺序表简单实现(总结)

在这里插入图片描述

特点

  1. 顺序表是有序有限,且元素数据类型相同的集合。
  2. 除第一个元素外,其他元素都有唯一的前驱元素
  3. 除最后一个元素外,其他的元素都有唯一的后继元素
  4. 顺序表中的元素总数n(n ≥ 0)即为顺序表的长度n = 0时,顺序表的长度为0,为空表。

功能实现

定义

#define SUC 1   		// 定义SUC 作为状态返回值,成功
#define ERR 0   		// 定义ERR 作为状态返回值,错误
#define TRUE 1  		// 定义TRUE 作为真假返回值,真
#define FALSE 0 		// 定义FALSE 作为真假返回值,假
#define MAXSIZE 20 		// 定义MAXSIZE为存储空间最大容量,依据情况而定

typedef int Status;     // 定义Status作为状态返回类型
typedef int Bool;       // 定义Bool 作为判断真假返回类型
typedef int ElemType ;  // ElemType 表示表中元素数据类型,依据情况而定
typedef struct       	// 定义存储结构
{
    ElemType data[MAXSIZE];   // 定义数组,作为顺序表的存储结构
    int len; 				// 定义len,表示【顺序表】长度
} SqList;

函数

初始化

功能:将顺序表长度初始化为0。

参数类型:SqList*

返回值类型:Status

Status InitList(SqList* L)
{
    L->len = 0;
    return SUC;
}

重置表

功能:将顺序表长度重置为0,置为空表,该操作是对于以创建顺序表的操作。

参数类型:SqList*

返回值类型:Status

Status ResetList(SqList* L)
{
    L->len = 0;
    return SUC;
}

获取表长

功能:获取顺序表的长度。

参数类型:SqList

返回值类型:int

int ListLength(SqList L)
{
    return L.len;
}

判断是否为空表

功能:判断顺序表是否为空表

参数类型:SqList

返回值类型:Bool

Bool isEmpty(SqList L)
{
    return L.len == 0 ? TRUE : FALSE;
}

访问元素

功能:输出指定元素至控制台

参数类型:ElemType

返回值类型:Status

Status visit(ElemType e)
{
    printf("%d ",e);
    return SUC;
}

遍历顺序表

功能:遍历顺序表中每个元素

参数类型:SqList

返回值类型:Status

Status ListTraverse(SqList L)
{
    int i = 0;
    int len = L.len;
    for(i = 0; i < len; i++)
    {
		visit(L.data[i]);
    }
    printf("\n");
    return SUC;
}

获取元素

功能:将指定位置上的元素的值赋值给接收元素

参数类型:SqListElemType*(接收元素)、int(位置)

返回值:Status

说明:

  1. 判断顺序表是否为空表?为空表返回ERR
  2. 判断指定位置是否合法?非法返回ERR
Status GetElem(SqList L, ElemType* e, int p)
{
    if(L.len == 0 || p < 1 || p > L.len)
    {
		return ERR;
    }
    *e = L.data[p - 1];
    return SUC;
}

查找元素

功能:查找指定元素在顺序表中的位置

参数类型:SqListElemType

返回值:int

说明:

  1. 判断顺序表是否为空表,空表返回0
  2. 遍历顺序表查找到则返回该位置,否则返回0
int LocataElem(SqList L, ElemType e)
{
    if(L.len == 0)
    {
        return 0;                  // 空表返回0 
    }
    int i = 0;
    for(i = 0; i < L.len; i++)
    {
        if(L.data[i] == e)
            return i + 1;         // 找到则返回位置
    }
    return 0;                     // 找不到则返回0
}

头插

功能:将元素添加至顺序表头。

参数类型:SqList*ElemType(添加的元素)

返回值类型:Status

说明:

  1. 判断顺序表是否已满
  2. 将所有元素整体后移一位
  3. 将元素添加至表头,表长+1
Status PushFront(SqList* L, ElemType e)
{
    int i = 0;        
    if (L->len == MAXSIZE)                // 判断顺序表是否已满
    {
        return ERR;
    }
    for (i = L->len - 1; i >= 0; i--)    
    {
        L->data[i + 1] = L->data[i];     // 将所有元素整体后移一位
    }
    L->data[0] = e;                      // 将元素添加至表头
    L->len++;                            // 表长+1
    return SUC;
}

尾插

功能:判断将元素添加至表尾

参数类型:SqList*ElemType(添加的元素)

返回值类型:Status

说明:

  1. 判断顺序表是否已满
  2. 将元素添加至表尾,表长+1
Status PushBack(SqList* L, ElemType e)
{
    if (L->len == MAXSIZE)                
    {
        return ERR;                      // 顺序表已满,则返回ERR
    }
                     
    L->data[L->len] = e;                 // 将元素添加至尾部,L->len是顺序表最后一个元素后一个位置,即表尾
    L->len++;                            // 顺序表长度+1
    return SUC;
}

指定位置插入元素

功能:将元素添加至顺序表中指定位置。

参数类型:SqList*ElemType(添加的元素)、int(位置)

返回值类型:Status

说明:

在添加元素前需要判断三点:

  1. 当前顺序表是否已满?

  2. 添加的位置是否不合理?

  3. 判断添加的位置是否在表尾?

    如果在表尾添加元素则不需要移动表中其他元素,否则需要将添加位置后的所有元素整体向后移动一位(包括添加位置的当前元素)。

添加完毕后,将表长+1,返回SUC

Status InsertPos(SqList* L, ElemType e, int p)
{
    if (L->len == MAXSIZE || p < 1 || p > L->len + 1)  // 判断顺序表是否已满,或则插入位置是否合理
    {                                                  //   L->len+1, 连续线性表,中间不能存在空位置
        return ERR;                 
    }
    if (p <= L->len)   			                     // 判断添加位置是否在表尾,表尾不需要移动表中其他元素
    {   // 进入语句,说明p不在表尾
        int i = 0;                   
        for (i = L->len - 1; i >= p - 1; i--)
        {
            L->data[i + 1] = L->data[i];             // 则需要将添加位置后的所有元素向后移动一位
        }
    }

    L->data[p - 1] = e;                               // 将指定元素添加到指定位置
    L->len++;                                         // 表长+1
    return SUC;
}

头删

功能:将顺序表头的元素删除

参数类型:SqList*ElemType*(接收删除的元素)

返回值类型:Status

说明:

  1. 判断表是否为空,为空返回ERR;
  2. 将顺序表说有元素整体前移一位
  3. 顺序表长度-1
Status PopFront(SqList* L, ElemType* e)
{
    if (L->len == 0)
        return ERR;                       // 顺序表为空,返回ERR
    *e = L->data[0];                      // 将被删除的元素赋值给*e
    int i = 0;
    for (i = 0; i < L->len - 1; i++)
    {
        L->data[i] = L->data[i + 1];       // 将所有元素整体前移一位
    }
    L->len--;                              // 顺序表长度减1
    return SUC;                            // 返回SUC
}

尾删

功能:将顺序表尾的元素删除

参数类型:SqList*ElemType*(接收删除的元素)

返回值类型:Status

说明:

  1. 判断表是否为空,为空返回ERR
  2. 变量接收被删除的元素
  3. 顺序表长度-1
Status PopBack(SqList* L, ElemType* e)
{
    if (L->len == 0)
        return ERR;                       // 顺序表为空,返回ERR
    *e = L->data[L->len - 1];             // 被删除的元素赋值给*e, L->len - 1为最后一个元素的下标
    L->len--;                             // 将表长-1,达到删除表尾元素目的
    return SUC;
}

指定位置删除元素

功能:删除顺序表指定位置元素

参数类型:SqList*ElemType*(接收删除的元素)、int(指定删除的位置)

返回值类型:Status

说明:

  1. 判断表是否为空,或者删除位置是否合法,如果为真,则返回ERR。
  2. 将被删除的元素赋值给外部变量。
  3. 判断删除位置是否为最后一个元素,若不是是最后一个元素则将删除位置后的所有元素整体前移一位。
  4. 顺序表长度-1。
  5. 返回SUC。
Status DeletePos(SqList* L, ElemType* e, int p)
{

    if (L->len == 0 || p < 1 || p > L->len)     // 判断表是否为空,或者位置是否合法
        return ERR;
    *e = L->data[p - 1];                       // 将被删除的元素赋值给*e
    if (p < L->len)                            // 判断删除位置是否为最后一个元素
    {
        int i = 0;
        for (i = p; i < L->len; i++)
        {
            L->data[i - 1] = L->data[i];      // 若不是最后一个元素则将删除位置后的所有元素整体前移一位
        }
    }
    L->len--;
    return SUC;
}

指定元素删除

功能:将指定的元素从顺序表中删除

参数类型:SqList*ElemType(指定删除元素)

返回值类型:Status

说明:

  1. 调用LocataElem() 函数获取指定元素的位置
  2. 如果LocataElem() 的返回值不为 0,调用DeletePos() 函数将指定元素删除,并返回SUC
  3. 否则返回ERR;
Status DeleteElem(SqList* L, ElemType* e)
{
    int p = LocataElem(*L, *e);            
    if (p)
    {
        DeletePos(L, e, p);
        return SUC;
    }
    return ERR;
}

合并表

功能:将存在于表b,不存在于表a的元素,添加进表a末尾

参数类型:SqList*SqList

返回值类型:void

说明:

  1. 访问表b中的问一个元素,需要用到GetElem()函数。
  2. 将获取的元素与La中的每一个元素进行对比。需要用到LocateElem()
  3. LocateElem()的返回值为0,则说明La中不存在这个元素。
  4. 调用PushBack()函数,将该元素添加至La表尾.
void UnionList(SqList* La, SqList Lb)
{
    ElemType e;                    // 元素e 用来比较两表中是否存在元素e
    // 获取两个表的长度
    int La_len = La->len;
    int Lb_len = Lb.len;
    int i = 0;
    for (i = 1; i <= Lb_len; i++)    // 获取Lb中的每一个元素
    {
        GetElem(Lb, &e, i);
        if (!LocataElem(*La, e))   // 如果La中没有该元素,将该元素添加至表尾。
        {
            PushBack(La, e);
        }
    }
}

测试代码

#define SUC 1   		// 定义SUC 作为状态返回值,成功
#define ERR 0   		// 定义ERR 作为状态返回值,错误
#define TRUE 1  		// 定义TRUE 作为真假返回值,真
#define FALSE 0 		// 定义FALSE 作为真假返回值,假
#define MAXSIZE 20 		// 定义MAXSIZE为存储空间最大容量,依据情况而定

typedef int Status;     // 定义Status作为状态返回类型
typedef int Bool;       // 定义Bool 作为判断真假返回类型
typedef int ElemType ; 	// ElemType 表示表中元素数据类型,依据情况而定
typedef struct       	// 定义存储结构
{
    ElemType data[MAXSIZE];    // 定义数组,作为线性表的存储结构
    int len; 				  // 定义len,表示【线性表】长度
} SqList;


// 初始化
Status InitList(SqList* L)
{
    L->len = 0;              // 将表长初始化为0,该操作是是对于新创建的表
    return SUC;              
}

// 重置表                   
Status ResetList(SqList* L)
{
    L->len = 0;              //  将顺序表长度重置为0,置为空表,该操作是对于以创建顺序表的操作。
    return SUC;
}

// 判断是否为空表
Bool isEmpty(SqList L)
{
    return L.len == 0 ? TRUE : FALSE;   
}

// 获取表长
int ListLength(SqList L)
{
    return L.len;          
}


// 访问元素
Status visit(ElemType e)
{
    printf("%d ", e);            // 打印元素
    return SUC;
}

// 遍历表
Status ListTraverse(SqList L)
{
    int i = 0;
    int len = L.len;
    for (i = 0; i < len; i++)   
    {
        visit(L.data[i]);       // 调用visit函数依次打印顺序表中的元素
    }
    printf("\n");
    return SUC;
}


// 获取元素
Status GetElem(SqList L, ElemType* e, int p)
{
    if (L.len == 0 || p < 1 || p > L.len)
    {
        return ERR;          // 空表,或位置不合法返回ERR
    }
    *e = L.data[p - 1];      // 将指定位置的元素赋值给e,e为真正的返回值
    return SUC;              // SUC为返回的状态
}

// 查找元素
int LocataElem(SqList L, ElemType e)
{
    if (L.len == 0)
    {
        return 0;                  // 空表返回0 
    }
    int i = 0;
    for (i = 0; i < L.len; i++)
    {
        if (L.data[i] == e)
            return i + 1;         // 找到则返回位置
    }
    return 0;                     // 找不到则返回0
}

// 头插
Status PushFront(SqList* L, ElemType e)
{
    int i = 0;        
    if (L->len == MAXSIZE)                
    {
        return ERR;                       // 顺序表已满,则返回ERR
    }
    for (i = L->len - 1; i >= 0; i--)    
    {
        L->data[i + 1] = L->data[i];     // 将所有元素整体后移一位
    }
    L->data[0] = e;                      // 将元素添加至表头
    L->len++;                            // 表长+1
    return SUC;
}

// 尾插
Status PushBack(SqList* L, ElemType e)
{
    if (L->len == MAXSIZE)                
    {
        return ERR;                      // 顺序表已满,则返回ERR
    }
                     
    L->data[L->len] = e;                 // 将元素添加至尾部,L->len是顺序表最后一个元素后一个位置,即表尾
    L->len++;                            // 顺序表长度+1
    return SUC;
}

// 按位置插入
Status InsertPos(SqList* L, ElemType e, int p)
{
    if (L->len == MAXSIZE || p < 1 || p > L->len + 1)  // 判断顺序表是否已满,或则插入位置是否合理
    {                                                  //   L->len+1, 连续线性表,中间不能存在空位置
        return ERR;
    }
    if (p <= L->len)   			                     // 判断添加位置是否在表尾,表尾不需要移动表中其他元素
    {   // 进入语句,说明p不在表尾
        int i = 0;
        for (i = L->len - 1; i >= p - 1; i--)
        {
            L->data[i + 1] = L->data[i];             // 则需要将添加位置后的所有元素向后移动一位
        }
    }

    L->data[p - 1] = e;                               // 将指定元素添加到指定位置
    L->len++;                                         // 表长+1
    return SUC;
}


// 头删
Status PopFront(SqList* L, ElemType* e)
{
    if (L->len == 0)
        return ERR;                       // 顺序表为空,返回ERR
    *e = L->data[0];                      // 将被删除的元素赋值给*e
    int i = 0;
    for (i = 0; i < L->len - 1; i++)
    {
        L->data[i] = L->data[i + 1];       // 将所有元素整体前移一位
    }
    L->len--;                             // 顺序表长度减1
    return SUC;                           // 返回SUC
}

// 头删
Status PopBack(SqList* L, ElemType* e)
{
    if (L->len == 0)
        return ERR;                       // 顺序表为空,返回ERR

    *e = L->data[L->len - 1];             // 被删除的元素赋值给*e, L->len - 1为最后一个元素的下标
    L->len--;                             // 将表长-1,达到删除表尾元素目的
    return SUC;
}



// 指定位置删除
Status DeletePos(SqList* L, ElemType* e, int p)
{

    if (L->len == 0 || p < 1 || p > L->len)     // 判断表是否为空,或者位置是否合法
        return ERR;
    *e = L->data[p - 1];                       // 将被删除的元素赋值给*e
    if (p < L->len)                            // 判断删除位置是否为最后一个元素
    {
        int i = 0;
        for (i = p; i < L->len; i++)
        {
            L->data[i - 1] = L->data[i];      // 若不是最后一个元素则将删除位置后的所有元素整体前移一位
        }
    }
    L->len--;
    return SUC;
}

// 指定元素删除
Status DeleteElem(SqList* L, ElemType* e)
{
    int p = LocataElem(*L, *e);
    if (p)
    {
        DeletePos(L, e, p);
        return SUC;
    }
    return ERR;
}


// 合并表
void UnionList(SqList* La, SqList Lb)
{
    ElemType e;                    // 元素e 用来比较两表中是否存在元素e
    // 获取两个表的长度
    int La_len = La->len;
    int Lb_len = Lb.len;
    int i = 0;
    for (i = 1; i <= Lb_len; i++)    // 获取Lb中的每一个元素
    {
        GetElem(Lb, &e, i);
        if (!LocataElem(*La, e))   // 如果La中没有该元素,将该元素添加至表尾。
        {
            PushBack(La, e);
        }
    }
}



int main()
{
    // 创建顺序表La,Lb
    SqList La,Lb; 

    // 创建接收ElemType类型变量
    ElemType elem;

    // 创建循环变量
    int i = 0;

    // 创建接收状态变量
    Status s = 0;

    // 创建接收真值变量
    Bool b = 0;

    // 创建接收int返回值变量
    int ret = 0;

    // 初始化顺序表La
    InitList(&La);

    // 在顺序表La的表头插入5个元素
    for (i = 1; i <= 5; i++)
    {
        PushFront(&La, i);
    }
    printf("1.  表头添加元素后:");
    ListTraverse(La);

    // 删除表头元素
    s = PopFront(&La,&elem);
    // 判断删除是否成功
    if (s)
    {
        printf("2.  被删除的元素是:%d\n", elem);
        printf("3.  删除表头元素后:");
        ListTraverse(La);

        // 获取顺序表当前长度
        ret = ListLength(La);
        printf("4.  顺序表当前长度为:%d\n", ret);
    }
    else
    {
        printf("2.  删除失败!\n");
    }


    // 重置顺序表
    s = ResetList(&La);
    printf("5.  顺序表是否重置成功?ret = %d(1. 成功 0. 失败)\n", s);

    // 判断顺序表是否为空 
    b = isEmpty(La);
    printf("6.  顺序表是否为空?    bl = %d(1. 是 0. 否)\n", b);

    // 再次在La的表尾处插入10个元素
    for (i = 1; i <= 10; i++)
    {
        PushBack(&La, i);
    }
    printf("7.  表尾添加元素后:");
    ListTraverse(La);
    
    // 删除表尾元素
    s =  PopBack(&La, &elem);
    // 判断删除是否成功
    if (s)
    {
        printf("8.  被删除的元素是:%d\n", elem);
        printf("9.  删除表尾元素后:");
        ListTraverse(La);

        // 获取顺序表当前长度
        ret = ListLength(La);
        printf("10. 顺序表当前长度为:%d\n", ret);
    }
    else
    {
        printf("8.  删除失败!\n");
    }


    // 在指定位置插入元素
    for (i = 5; i <= 8; i++)
    {
        InsertPos(&La, 233, i);
    }
    printf("11. 指定位置插入元素后:");
    ListTraverse(La);

    // 在指定位置删除元素
    printf("12. 指定位置被删除元素是:");
    for (i = 1; i <= 3; i++)
    {
        DeletePos(&La, &elem, i);
        printf("%d ", elem);
    }
    printf("\n13. 删除指定位置的元素后:");
    ListTraverse(La);

    // 获取顺序表当前长度
    ret = ListLength(La);
    printf("14. 顺序表当前长度为:%d\n", ret);

    // 获取指定位置的元素
    printf("15. 查找指定位置元素为:");
    for (i = 0; i < 3; i++)
    {
        s = GetElem(La, &elem, i);
        if (s)
        {
            printf("%d ", elem);
        }
        else 
        {
            printf("该元素不存在! ");
        }
    }

    // 查找元素
    elem = 233;
    ret = LocataElem(La, elem);
    printf("\n16. 查找元素%d的位置在:第%d个\n", elem, ret);
    
    // 删除指定元素
    s = DeleteElem(&La, &elem);
    if (s)
    {
        printf("17. 删除元素%d成功!\n", elem);
    }
    else
    {
        printf("17. 删除失败!\n");
    }

    printf("18. 删除指定元素后:");
    ListTraverse(La);

    // 获取顺序表当前长度
    ret = ListLength(La);
    printf("19. 顺序表当前长度为:%d\n", ret);

    // 初始化顺序表Lb
    InitList(&Lb);

    // 表尾插入元素
    for (i = 5; i <= 15; i++)
    {
        PushBack(&Lb, i);
    }
    printf("20. 在表Lb的尾部插入元素后:");
    ListTraverse(Lb);

    // 合并表,将Lb中存在,la中不存在的添加到La中
    UnionList(&La, Lb);
    printf("21. 两表合并后La表的元素有:");
    ListTraverse(La);
    return 0;
}

在这里插入图片描述

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值