11-针对顺序表基本运算设计实现的改进

第10篇中,我们介绍了顺序表的基本运算的实现,现在再对顺序表的基本运算实现做一些简单的改进:
  1. 改进顺序表的存储结构和基本运算

  2. 对于顺序表的基本运算做好错误处理

  3. 函数的声明和实现分开,即函数声明放在sqlist.h文件,实现放sqlist.c文件,测试文件main.c

sqlist.h文件
#ifndef SQLIST_H
#define SQLIST_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

//顺序表的存储结构定义
typedef struct SQLIST{
    int* DataAddr;  //存放数据的首地址
    int length;         //顺序表的有效长度
    int MaxSize;        //顺序表的空间大小,表示顺序表最多能存储多少元素
} SqList;

/*
    功能:初始化顺序表
    参数1: void (无)
    返回值:成功返回顺序表的地址,失败返回NULL
*/
SqList* Init_List();

/*
    功能: 实现数据元素插入

    参数: 
          1. 要操作的顺序表
          2. 要插入的数据元素

    返回值:成功返回0,失败返回-1
*/
int Insert_Element_List(SqList* sqlist , int element);

/*
    功能:根据位置删除数据元素

    参数
         1:要操作的顺序表
         2:要删除的数据元素的位置

    返回值:成功返回0,失败返回-1
*/
int RemoveByPos_List(SqList* sqlist , int pos);

/*
    功能:根据数据的值删除数据

    参数
         1:要操作的顺序表
         2:要删除的数据元素

    返回值:成功返回0,失败返回-1
*/
int RemoveByElement_List(SqList* sqlist, int element);

/*
    功能:查找顺序表中的数据元素

    参数 
        1:要操作的顺序表
        2:要查找的数据

    返回值:成功返回0,失败返回-1
*/
int Select_List(SqList* sqlist, int element);

/*
    功能:把顺序表中的数据元素全部打印出来

    参数
        1:要操作的顺序表

    返回值:成功返回0,失败返回-1

*/
void Print_List(SqList* sqlist);

//释放顺序表的内存
void Free_List(SqList* sqlist);

//清空顺序表
void Clear_List(SqList* sqlist);

//获得顺序表的大小
int GetSize_List(SqList* sqlist);

//获得顺序表当前元素个数
int GetLength_List(SqList* sqlist);

//根据位置获得某个位置元素
int GetByPos_List(SqList* sqlist,int pos);

#endif

以下是主要的算法实现思路:
1.Init_List()初始化实现思路:
 申请内存
 初始化顺序表的长度
 设置初始顺序表的大小
 申请数据存储空间的内存

2.Insert_Element_List()插入算法实现思路:
 判断传入的顺序表是否合法
 判断存储空间是否足够
   如果不够分配新的存储空间
   把数据拷贝到新空间中
   释放旧的存储空间
   更新顺序表的大小
   更新数据存储空间的指向
 在末尾插入数据,并更新顺序表的长度

3.RemoveByPos_List()删除算法思路:
 判断判断传入的顺序表和位置是否合法
 再判断是否为要删除最后一个数据元素,如果是则顺序表长度-1
 删除元素,后面的往前覆盖
 更新顺序表长度


sqlist.c文件
#include "sqlist.h"

/*
    功能:初始化顺序表

    参数1: void (无)

    返回值:成功返回顺序表的地址,失败返回NULL
*/
SqList* Init_List()
{
    //给顺序表申请内存
    SqList *list = (SqList *)malloc(sizeof(SqList));
    //初始化顺序表的长度
    list->length = 0;
    //设置初始顺序表的大小为50
    list->MaxSize = 50;
    //申请数据存储空间的内存
    list->DataAddr = (int *)malloc(sizeof(int) * list->MaxSize);
    //返回顺序表的地址
    return list;
}

/*
    功能: 实现数组元素插入

    参数: 
          1. 要操作的顺序表
          2. 要插入的数据元素

    返回值:成功返回0,失败返回-1
*/
int Insert_Element_List(SqList* sqlist , int element)
{
    //判断传入的顺序表是否合法
    if (NULL == sqlist)
    {
        //传入的sqlist非法,返回-1
        return -1;
    }
    //判断顺序表存储空间是否足够
    if(sqlist->length == sqlist->MaxSize)
    {
        //如果不够分配新的存储空间,大小为旧空间的2倍
        int *newDataAddr = (int *)malloc(sizeof(int) * sqlist->MaxSize * 2);
        //把数据从旧的空间中拷贝到新空间中
        memcpy(newDataAddr,sqlist->DataAddr,sqlist->MaxSize);
        //释放旧的存储空间
        free(sqlist->DataAddr);
        //更新顺序表的大小
        sqlist->MaxSize = sqlist->MaxSize * 2;
        //更新数据存储空间的指向
        sqlist->DataAddr = newDataAddr;
    }
    //在末尾插入数据元素
    sqlist->DataAddr[sqlist->length] = element;
    //更新顺序表的长度
    sqlist->length++;
    return 0;
}

/*
    功能:根据位置删除数据元素

    参数
         1:要操作的顺序表
         2:要删除的数据元素的位置

    返回值:成功返回0,失败返回-1
*/
int RemoveByPos_List(SqList* sqlist , int pos)
{
    //判断判断传入的顺序表和位置是否合法
    if(NULL == sqlist || pos < 0 || pos >= sqlist->length)
    {
        return -1;
    }

    //判断是否为删除最后一个元素
    if(pos != sqlist->length -1)
    {
        //删除元素
        int i;
        for(i = pos; i < sqlist->length; i++)
        {   //后面的往前覆盖
            sqlist->DataAddr[i] = sqlist->DataAddr[i+1];
        }
    }

    //更新顺序表长度
    sqlist->length--;
    return 0;
}

/*
    功能:根据数据的值删除数据

    参数
         1:要操作的顺序表
         2:要删除的数据元素

    返回值:成功返回0,失败返回-1
*/
int RemoveByElement_List(SqList* sqlist, int element)
{
    //判断传入的顺序表是否合法,顺序表大小是否为空
    if(sqlist == NULL || sqlist->length == 0)
    {
        return -1;
    }
    //这里直接判断是否要删除最后一个元素
    if(element == sqlist->DataAddr[sqlist->length -1])
    {
        //如果是直接把顺序表的长度-1
        sqlist->length--;
        return 0;
    }
    //注意前面已经判断过一次了,因此这里要少判断一次,所以length - 1
    //同时也为了防止指针越界
    int i;
    for(i = 0; i < sqlist->length - 1; i++)
    {
        //是否是要删除的元素
        if(sqlist->DataAddr[i] == element)
        {
            sqlist->DataAddr[i] = sqlist->DataAddr[i+1];
            sqlist->length--;
            return 0;
        }
    }
    //跳出循环说明没找到要删除的元素,直接返回-1
    return -1;
}

/*
    功能:查找顺序表中的数据元素

    参数 
        1:要操作的顺序表
        2:要查找的数据

    返回值:成功返回元素的索引下标,失败返回-1
*/
int Select_List(SqList* sqlist, int element)
{
    if(NULL == sqlist)
    {
        return -1;
    }

    int i = 0;
    for(i = 0; i < sqlist->length; i++)
    {   //查找到就返回元素的索引下标
        if(sqlist->DataAddr[i] == element)
        {
            return i;
        }
    }


    return -1;
}

/*
    功能:把顺序表中的数据元素全部打印出来

    参数
        1:要操作的顺序表

    返回值:成功返回0,失败返回-1
*/
void Print_List(SqList* sqlist)
{
    if(NULL == sqlist)
    {
        return;
    }

    int i = 0;
    for(i = 0; i < sqlist->length; i++)
    {
    printf("%d\n" , sqlist->DataAddr[i]);
    }

}

//释放顺序表的内存
void Free_List(SqList* sqlist)
{
    if (NULL == sqlist)
    {
        return;
    }

    if(sqlist->DataAddr != NULL)
    {
        free(sqlist->DataAddr);
        sqlist->DataAddr = NULL;
    }

    free(sqlist);
    sqlist = NULL;
}

//清空顺序表
void Clear_List(SqList* sqlist)
{
    if(NULL == sqlist)
    {
        return;
    }
    //直接把顺序表长度改为0
    sqlist->length = 0;
}

//获得顺序表大小
int GetSize_List(SqList* sqlist)
{
    if(NULL == sqlist)
    {
        return -1;
    }
    return sqlist->MaxSize;
}

//获得顺序表当前元素个数,也就是顺序表的长度
int GetLength_List(SqList* sqlist)
{
    if(NULL == sqlist)
    {
        return -1;
    }
    return sqlist->length;
}

//根据位置获得某个位置元素
int GetByPos_List(SqList* sqlist,int pos)
{

    if(sqlist == NULL)
    {
        return -1;
    }
    //索引下标是否合法
    if(pos < 0 || pos >= sqlist->length)
    {
        return -1;
    }

    //直接返回下标索引的数据元素
    return sqlist->DataAddr[pos];
}


/*
    功能:删除顺序表中所有重复的元素

    参数
        1:要操作的顺序表
        2:要删除的元素

    返回值: 无
*/
void Remove_node(SqList* sqlist , int element)
{

    if(NULL == sqlist)
    {
        return;
    }

    int pos;
    //通过Select_List查找要删除的元素x,并返回该元素的位置i
    while((pos = Select_List(sqlist, element)) >= 0)
    {
         //然后根据位置i删除元素
        RemoveByPos_List(sqlist , pos);
    }
}




//x为要删除的数据元素
void Remove_node2(SqList* sqlist , int element)
{

    //size记录非x的元素个数
    int size = 0;
    int i;
    for(i = 0; i < sqlist->length; i++)
    {   
        //把不重复的数据元素复制到顺序表L1中
        if(sqlist->DataAddr[i] != element)
        {
            sqlist->DataAddr[size] = sqlist->DataAddr[i];
            size++;
        }
    }
    //然后把不重复的元素个数赋值给length
    sqlist->length = size;
}
main.c测试文件
#define _CRT_SECURE_NO_WARNINGS
#include "sqlist.h"

int main(void)
{
    //初始化顺序表
    SqList *sqlist = Init_List();
    printf("顺序表长度:%d\n", GetLength_List(sqlist));
    printf("顺序表大小:%d\n", GetSize_List(sqlist));
    //插入元素  
    printf("------------插入元素------------\n");
    int i;
    for(i = 0; i < 5; i++)
    {
        Insert_Element_List(sqlist,i);
    }
    printf("顺序表长度:%d\n", GetLength_List(sqlist));
    printf("顺序表大小:%d\n", GetSize_List(sqlist));
    printf("------------打印全部元素---------------\n");
    //打印全部的元素
    Print_List(sqlist);
    printf("------------删除元素4后-----------\n");
    RemoveByElement_List(sqlist , 4);
    Print_List(sqlist);
    printf("------------插入元素5后-----------\n");
    Insert_Element_List(sqlist, 5);
    Print_List(sqlist);
    printf("------------查询第三个位置的元素-----------\n");
    printf("第三个位置的元素:%d\n", GetByPos_List(sqlist , 2));
    printf("------------Clear_List清空元素-----------\n");
    Clear_List(sqlist);
    Print_List(sqlist);
    printf("------------Free_List释放内存-----------\n");
    Free_List(sqlist);

    return 0;
}



打开cmd窗口执行以下命令:

gcc -o main main.c sqlist.c sqlist.h
main



测试结果:
这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值