顺序表的实现
1.顺序表的定义与相关注意
顺序表的逻辑结构下标从1开始依次向后增加,而存储结构是相当于数组般,从0开始往后进行存储,因此逻辑位序和物理位序相差1,如下图所示:
其类型定义:
其中元素是以数组的方式存储的,也就是L.elem[ i ]的样式,而在线性表L中,是存储在一个内存块中的,其表示可如图显示
2.顺序表操作函数定义
添加操作进行在下标为i的位置插入一个元素图解:
具体操作就是借用指针来进行操作,具体如下图所示:
3.代码以及运行结果
test.c
#include "Operation.h"
int main()
{
SqList L;
int i;
int e;
//初始化
InitList_Sq(&L);
if (!InitList_Sq(&L))
{
printf("初始化错误");
return -1;
}
// 插入数据
for (i = 1; i <= 10; i++)
{
ListInsert(&L, i, i);
}
printf("输出顺序表内容:");
// 打印数据
ListPrint(L);
// 查找数据
printf("请输入查找的数据:");
scanf("%d", &e);
if (LocateElem(L, e))
{
printf("查找成功,元素下标为%d \n", LocateElem(L, e));
}
else {
printf("查找失败!\n");
}
// 获取第i位置的元素内容
printf("请输入查找元素下标:");
scanf("%d", &i);
if (GetElem(L, i, &e))
{
printf("查找到第%d个元素为%d \n", i, e);
}
else {
printf("查找失败!\n");
}
// 删除数据
printf("请输入要删除的元素下标:");
scanf("%d", &i);
if (ListDelete(&L, i, &e))
{
printf("删除成功,删除的元素为%d\n", e);
}
else {
printf("删除失败!\n");
}
// 打印数据
ListPrint(L);
// 清空线性表
ClearList(&L);
// 打印数据
ListPrint(L);
// 销毁已存在的线性表
DestroyList(&L);
// 打印数据
ListPrint(L);
return 0;
}
头文件:Operation.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INFEASIBLE -1
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
#define LISTINCREMENT 10
typedef struct
{
ElemType* elem;
int length;
}SqList; //定义顺序表类型
//初始化顺序表
Status InitList_Sq(SqList* L);
// 插入数据
Status ListInsert(SqList* L,int i,ElemType e);
// 打印数据
Status ListPrint(SqList L);
// 查找数据
Status LocateElem(SqList L,ElemType e);
// 获取第i位置的元素内容
Status GetElem(SqList L,int i, ElemType* e);
// 删除数据
Status ListDelete(SqList* L,int i,ElemType* e);
// 清空线性表
Status ClearList(SqList* L);
// 销毁已存在的线性表
Status DestroyList(SqList* L);
//判断错误问题
void QuestPrint(int Q);
对函数的实现Operation.c
#include "Operation.h"
//初始化顺序表
Status InitList_Sq(SqList* L) {
L->elem = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);
if (!L->elem) exit(OVERFLOW);
L->length = 0;
return OK;
}
// 插入数据
Status ListInsert(SqList* L, int i, ElemType e)
{
int* Newbase;
//判断i是否在线性表的长度范围内
if (i >= 1 && i <= L->length + 1)
{
//判断线性表的长度是否还有内存,如果已经初始化的最大内存,自动扩存
if (L->length >= MAXSIZE)
{
Newbase = (int*)malloc((MAXSIZE + LISTINCREMENT) * sizeof(int));
}
//定义两个指针变量,p取得elem数组中的i-1个位置,然后将i-1位置的元素往后移一个位置
//即i-1位置的元素到i位置
int* p, * q;
p = &(L->elem[i - 1]);
for (q = &(L->elem[L->length - 1]); q >= p; --q)
{
*(q + 1) = *q; //将原来是q地址的元素放到q+1地址里头
}
//将e赋值到p的位置里
*p = e;
++L->length;
return OK;
}
else { //i不在L的长度内
return OVERFLOW;
}
}
// 打印数据
Status ListPrint(SqList L)
{
if (L.length) {
//从0开始遍历elem数组,输出线性表长度length个元素
for (int i = 0; i < L.length; i++)
{
printf("%d ", L.elem[i]);
}
printf("\n");
return OK;
}
else {
return INFEASIBLE;
}
}
// 查找数据
Status LocateElem(SqList L, ElemType e)
{
if (L.length)
{
int i = 0;
for (i = 0; i < L.length; i++)
{
if (L.elem[i] == e) {
return i;
break;
}
}
return FALSE;
}
else
{
return INFEASIBLE;
}
}
// 获取第i位置的元素内容
Status GetElem(SqList L, int i, ElemType* e)
{
if (i >= 0 && i < L.length) {
*e = L.elem[i];
return TRUE;
}
else {
return FALSE;
return OVERFLOW;
}
}
// 删除数据
Status ListDelete(SqList* L, int i, ElemType* e)
{
if (i >= 0 && i <= L->length) {
*e = L->elem[i - 1];
int* p;
//p在最后一个地址之前,将后面元素赋给前面一个地址,依次往后移
for (p = &(L->elem[i - 1]); p <= &(L->elem[L->length - 1]); ++p)
{
*p = *(p + 1); //将后面的元素都往前挪一个地址
}
L->length = L->length - 1;
return TRUE;
}
else {
return FALSE;
return OVERFLOW;
}
}
// 清空线性表
Status ClearList(SqList* L)
{
L->length = 0;
printf("已经清空线性表,当前长度为0!\n");
return OK;
}
// 销毁已存在的线性表
Status DestroyList(SqList* L)
{
if (L->elem)
{
free(L->elem);
printf("销毁成功,当前线性表元素为0!\n");
return OK;
}
else {
return INFEASIBLE;
}
}
//判断错误问题
void QuestPrint(int Q)
{
if (Q == 0)
{
printf("出错了!");
}
if (Q == -1)
{
printf("线性表为空,或者不存在!");
}
if (Q == -2)
{
printf("不在查询范围内!");
}
}
运行结果:
顺序表的实现相对比较简单,跟数组的操作类似,差不多就只有插入的操作有些许难理解,其他都比较简单。