数据结构 - 静态顺序线性表的实行(C语言)
1 获取元素操作
对于线性表的顺序存储结构来说,如果我们要实现GetElem操作,即将线性表L中的第i个位置元素值返回,其实是非常简单的。 只要i的数值在数组下标范围内,就是把数组第i下标的值返回即可。 来看代码:
/******************************************
名称: 获取元素操作
功能: 将线性表pSeqList中的第i个位置元素值返回给e
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status GetElem(SeqList *pSeqList, int i, ElemType *e)
{
//前提条件: 顺序线性表已存在,且i在合理范围内:0 <= i <= ListLength-1(pSeqList)
if (pSeqList->length == 0 || i < 0 || i>pSeqList->length-1) //若pSeqList.length==0,则说明顺序线性表不存在
return FALSE;
*e = pSeqList->data[i];
return TRUE;
}
2 插入操作
插入数据的实现过程如下图所示:
插入算法的思路;
- 判断插入位置是否合理,不合理则抛出异常;
- 判断线性表长度是否大于等于数组长度,是则抛出异常或动态增加容量;
- 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;
- 将要插入元素填入位置i处;
- 表长加1。
实现代码如下:
/******************************************
名称: 插入元素操作
功能: 在线性表pSeqList中的第i个位置插入元素e
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status ListInsert(SeqList *pSeqList, int i, ElemType e)
{
int k;
//判断插入位置是否合理,不合理则抛出异常
if (i < 0 || i > pSeqList->length)
return FALSE;
//判断线性表长度是否大于等于数组长度,是则抛出异常或动态增加容量
if (pSeqList->length >= MAX_SIZE)
return FALSE;
//从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置
//有一种特殊情况不用后移: 当插入元素到表尾的下一个位置
if (i <= pSeqList->length-1) //若插入数据位置在表尾或更前面,表尾为最后一个元素的位置
{
//将插入位置及后面元素向后移动一位
for (k = pSeqList->length-1; k>=i; k--)
pSeqList->data[k+1] = pSeqList->data[k];
}
//将要插入元素填入位置i处
pSeqList->data[i] = e;
//表长加1
pSeqList->length++;
return TRUE;
}
注意:插入位置可以是表尾元素的下一个位置,那样不需要后移元素。
3 删除操作
线性表的顺序存储结构删除元素的过程如下图所示:
删除算法的思路:
- 判断线性表是否为空,为空则抛出异常;
- 判断删除位置是否合理,不合理则抛出异常;
- 取出删除元素;
- 从删除元素的下一个位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
- 表长减1。
实现代码如下:
/******************************************
名称: 删除元素操作
功能: 删除线性表pSeqList中的第i个位置的元素,并用e返回其值
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status ListInsert(SeqList *pSeqList, int i, ElemType *e)
{
int k;
//判断线性表是否为空,为空则抛出异常
if (pSeqList->length == 0)
return FALSE;
//判断删除位置是否合理,不合理则抛出异常
if (i < 0 || i > pSeqList->length-1)
return FALSE;
//取出删除元素
*e = pSeqList->data[i];
//从删除元素的下一个位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
if (i != pSeqList->length-1) //若删除位置在表尾,则不需要前移
{
//将删除元素的下一个位置及后面元素向前移动一位
for (k = i+1; k <= pSeqList->length-1; k++)
pSeqList->data[k-1] = pSeqList->data[k];
}
//表长减1
pSeqList->length--;
return TRUE;
}
注意:若pSeqList->length等于0,则说明线性表为空。
4 综合程序
/*
* 几个注意点:
* 1.初始化时,应考虑数组大小为负的情况
* 2.在各操作中,当涉及到位置i时,都应考虑i位置不合理的情况
* 3.插入操作中,需考虑线性表已满的情况
* 删除、获取操作中,需考虑线性表为空的情况
* 4.插入删除操作中,均应考虑插入或删除位置为表尾情况(似乎没必要)
* 5.插入删除操作中,别忘了最后要改变表长
*/
#include "stdafx.h"
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Status; //Status是函数结果状态,成功返回TRUE,失败返回FALSE
#define MAX_SIZE 100 //静态顺序线性表的最大容量
typedef int ElemType;
//定义静态顺序线性表
typedef struct
{
ElemType data[MAX_SIZE];
int length; //静态顺序线性表的元素个数
}SeqList;
SeqList *InitList(); //初始化操作
void ListDestroy(SeqList *pSeqList); //销毁线性表操作
Status ListEmpty(SeqList *pSeqList); //检测是否为空操作
Status ClearList(SeqList *pSeqList); //清空线性表操作
int ListLength(SeqList *pSeqList); //获取元素个数操作
Status GetElem(SeqList *pSeqList, int i, ElemType *e); //获取元素操作
int LocateElem(SeqList *pSeqList, const ElemType e); //查找元素位置操作
Status ListInsert(SeqList *pSeqList, int i, const ElemType e); //插入元素操作
Status ListInsert(SeqList *pSeqList, int i, ElemType *e); //删除元素操作
/******************************************
名称: 初始化操作
功能: 建立一个空的线性表pSeqList
******************************************/
SeqList *InitList()
{
SeqList *pSeqList = (SeqList *)malloc(sizeof(SeqList));
if (pSeqList == NULL)
{
printf("InitList malloc error!\n");
exit(1);
}
pSeqList->length = 0;
return pSeqList;
}
/******************************************
名称: 销毁线性表操作
功能: 释放线性表指针申请内存,并指向NULL
******************************************/
void ListDestroy(SeqList *pSeqList)
{
free(pSeqList);
pSeqList = NULL;
}
/******************************************
名称: 检测是否为空操作
功能: 若线性表元素个数为0,则认为线性表为空
返回值: 若线性表为空,返回true,否则返回false
******************************************/
Status ListEmpty(SeqList *pSeqList)
{
return pSeqList->length == 0 ? TRUE :FALSE;
}
/******************************************
名称: 清空线性表操作
功能: 将线性表清空:将长度清零即可
返回值: 若线性表成功清空,返回true,否则返回false
******************************************/
Status ClearList(SeqList *pSeqList)
{
pSeqList->length = 0;
return TRUE;
}
/******************************************
名称: 获取元素个数操作
功能: 获取线性表pSeqList的元素个数
返回值: 线性表元素个数
******************************************/
int ListLength(SeqList *pSeqList)
{
return pSeqList->length;
}
/******************************************
名称: 获取元素操作
功能: 将线性表pSeqList中的第i个位置元素值返回给e
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status GetElem(SeqList *pSeqList, int i, ElemType *e)
{
//前提条件: 顺序线性表已存在,且i在合理范围内:0 <= i <= ListLength(pSeqList)
if (pSeqList->length == 0 || i < 0 || i>pSeqList->length) //若pSeqList.length==0,则说明顺序线性表不存在
return FALSE;
*e = pSeqList->data[i];
return TRUE;
}
/******************************************
名称: 查找元素位置操作
功能: 在线性表pSeqList中查找与给定值e相等的元素索引
返回值: 查找成功返回元素所在的位置索引,失败返回-1(不能返回0)
******************************************/
int LocateElem(SeqList *pSeqList, const ElemType e)
{
//遍历并显示线性表元素
for (int i = 0; i < pSeqList->length; i++)
{
if (e == pSeqList->data[i])
return i;
}
return -1;
}
/******************************************
名称: 插入元素操作
功能: 在线性表pSeqList中的第i个位置插入元素e
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status ListInsert(SeqList *pSeqList, int i, const ElemType e)
{
int k;
//判断插入位置是否合理,不合理则抛出异常
if (i < 0 || i > pSeqList->length)
return FALSE;
//判断线性表长度是否大于等于数组长度,是则抛出异常或动态增加容量
if (pSeqList->length >= MAX_SIZE)
return FALSE;
//从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置
//有一种特殊情况不用后移: 当插入元素到表尾的下一个位置
if (i <= pSeqList->length-1) //若插入数据位置在表尾或更前面,表尾为最后一个元素的位置
{
//将插入位置及后面元素向后移动一位
for (k = pSeqList->length-1; k>=i; k--)
pSeqList->data[k+1] = pSeqList->data[k];
}
//将要插入元素填入位置i处
pSeqList->data[i] = e;
//表长加1
pSeqList->length++;
return TRUE;
}
/******************************************
名称: 删除元素操作
功能: 删除线性表pSeqList中的第i个位置的元素,并用e返回其值
返回值: Status是函数结果状态,成功返回TRUE,失败返回FALSE
******************************************/
Status ListInsert(SeqList *pSeqList, int i, ElemType *e)
{
int k;
//判断线性表是否为空,为空则抛出异常
if (pSeqList->length == 0)
return FALSE;
//判断删除位置是否合理,不合理则抛出异常
if (i < 0 || i > pSeqList->length-1)
return FALSE;
//取出删除元素
*e = pSeqList->data[i];
//从删除元素的下一个位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
if (i != pSeqList->length-1) //若删除位置在表尾,则不需要前移
{
//将删除元素的下一个位置及后面元素向前移动一位
for (k = i+1; k <= pSeqList->length-1; k++)
pSeqList->data[k-1] = pSeqList->data[k];
}
//表长减1
pSeqList->length--;
return TRUE;
}
/******************************************
名称: 遍历操作
功能: 遍历并显示线性表元素
返回值: 查找成功返回元素所在的位置索引,失败返回-1(不能返回0)
******************************************/
void ListTraverse(SeqList *pSeqList)
{
for (int i = 0; i < pSeqList->length; i++)
printf("%d ", pSeqList->data[i]);
printf("\n");
}
int main()
{
//初始化静态线性表
SeqList *pSeqList = InitList();
//检测线性表是否为空
if (ListEmpty(pSeqList))
printf("线性表为空!\n");
else
printf("线性表不为空!\n");
//插入元素到静态线性表
ListInsert(pSeqList, 0, 0);
ListInsert(pSeqList, 1, 1);
if ( ListInsert(pSeqList, 0, 2) ) //在位置0插入,后面位置的元素后移一位
printf("元素插入成功!\n");
//在线性表中删除元素
int value1;
if (ListInsert(pSeqList, 2, &value1) == FALSE)
{
printf("error!\n");
return -1;
}
printf("删除的元素为:%d\n", value1);
//获取元素个数
printf("元素个数为%d个\n", ListLength(pSeqList));
//查找元素位置
printf("查找到元素的位置为:%d\n", LocateElem(pSeqList, 0));
//遍历并显示线性表元素
printf("遍历线性表: ");
ListTraverse(pSeqList);
//清空线性表
printf("清空线性表!");
ClearList(pSeqList);
//销毁线性表
ListDestroy(pSeqList);
printf("\n");
return 0;
}
/*
输出结果:
线性表为空!
元素插入成功!
删除的元素为:1
元素个数为2个
查找到元素的位置为:1
遍历线性表: 2 0
清空线性表!
*/
注意上面只是“静态顺序线性表”的C语言实现,只实现了一些最基本的操作,有兴趣的同学可以在这上面扩展。