在第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
测试结果: