题目
编写C应用程序,实现顺序表上的如下操作:初始化,销毁,插入,删除,定位,求表长、“判空”以及“存取第 i 个数据元素”。
提示:以下是本篇文章正文内容,下面案例可供参考
一、数据结构设计
线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,一般采用数组存储,在数组上完成增删改查等算法
二、线性表的类型定义
线性结构是一个数据元素的有序(次序)集
线性结构的基本特征
存在唯一的一个被称作“第一个”的数据元素
存在唯一的一个被称作“最后一个”的数据元素
除第一个外,集合中的每个数据元素均只有一个前驱
除最后一个外,集合中的每个数据元素均只有一
个后继
线性表:n个数据元素组成的有限序列。表示为(a1,a2,…,ai,ai+1,…,an)
例如:英文字母表(A,B,C,……Z)是一个线性表
ADT线性表的定义
三、线性表的顺序储存表示
线性表的顺序存储可用一组地址连续的存储单元依次储存线性表的数据元素。
1、顺序表的类型定义
typedef struct {
ElemType* elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
2、顺序表的核心操作
1.初始化操作
算法声明:InitList(&L)
功能:构造一个空的顺序表。
方法:首先要按需为其动态分配一个存储区域,然
后设其当前长度为0。
//顺序表的类型定义
typedef struct {
ElemType* elem; //基址
int length; //长度
int listsize; //存储容量
}SqList;
2.查找操作
算法: LocateElem(L,e,compare( ))
功能:在顺序表中查询第一个满足判定条件的数据元素,若存在,则返回它的位序,否则返回 0
方法:将顺序表中的元素逐个和给定值e相比较。
//查找
int LocateElem_Sq(SqList L, ElemType e,int (*compare)(ElemType, ElemType)){
int i = 1;
ElemType* p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))
++i;
if (i <= L.length)
return i;
else return 0;
}
3.插入操作
算法:ListInsert(&L,i, e)
功能:将数据元素插入到线性表的指定位置
方法:第i个元素位置后的元素全部后移,在第i个元素前插入元素
时间复杂度为:O( ListLength(L) )
//插入
Status ListInsert_Sq(SqList& L, int i, ElemType e) {
if (i<1 || i>L.length + 1) { //i值不合法
return ERROR;
printf("i值不合法\n");
}
if (L.length >= MAXSIZE) { //存储空间已满 增加分配
ElemType* newbase = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) { //存储分配失败
printf("存储分配失败!");
exit(OVERFLOW);
}
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
ElemType *q = &(L.elem[i - 1]);
for (ElemType* p = &(L.elem[L.length - 1]); q <= p; --p) {
*(p+1)=*p;
}
*q=e;
++L.length;
return OK;
}
4.删除操作
算法:ListDelete_Sq(Sqlist& L, int i, int& e)
功能删除指定位置的元素
方法:在第i个元素位置后的元素全部左移
时间复杂度:O(ListLength(L))
//删除
Status ListDelete_Sq(SqList& L, int i, int& e) {
if (i<1 || i>L.length) { //i值不合法
printf("i值不合法!\n");
return ERROR;
}
ElemType* p = &(L.elem[i - 1]);
e = *p;
ElemType* q = L.elem + L.length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *p;
--L.length;
return OK;
}
5.销毁操作
算法:DestroyList_Sq(Sqlist& L)
功能:销毁线性表
方法:释放顺序表存储空间并清空指针域,表长置为零,存储容量设置为零。
//销毁
void DestroyList_Sq(SqList& L) {
if (L.elem)
delete L.elem;
}
6.存取操作
算法:GetElem(Sqlist L, int i)
方法:返回第i个元素的值
//存取
int GetElem(SqList L, int i) {
if (i<1 || i>L.length)
return ERROR;
return L.elem[i - 1];
}
7.求表长操作
算法:ListLength(Sqlist L)
方法:返回顺序表的表长
//求表长
int GetLength(SqList L) {
return L.length;
}
8.判空操作
算法:ListEmpty(Sqlist L)
功能:判断线性表是否为空
方法:判断单线性表的长度,若表长为0则返回0,若表长不为0则返回1。
//判空
int IsEmpty(SqList L) {
if (L.length == 0)
return 1;
else
return 0;
}
源代码及实现
sqlist.h
#pragma once
#define MAXSIZE 100
//函数结果状态代码
#define LISTINCREMENT 10
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
//预类型定义
typedef int Status;
typedef int ElemType;
//初始化
Status InitList_Sq(SqList& L);
//插入
Status ListInsert_Sq(SqList& L, int i, ElemType e);
//删除
Status ListDelete_Sq(SqList& L, int i, ElemType& e);
//查找
int LocateElem_Sq(SqList L, ElemType e,
int (*compare)(ElemType, ElemType));
//比较
int compare(ElemType a, ElemType b);
//求表长
int GetLength(SqList L);
//判空
int IsEmpty(SqList L);
//存取
int GetElem(SqList L, int i);
//打印
void ListPrint(SqList L);
//销毁
void DestroyList_Sq(SqList& L);
sqlist.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "sqlist.h"
#include <stdlib.h>
//初始化操作
Status InitList_Sq(SqList& L) {
L.elem = (ElemType*)malloc(MAXSIZE * sizeof(ElemType));
if (!L.elem) {
printf("存储分配失败!\n");
exit(OVERFLOW);
}
L.length = 0;
L.listsize = MAXSIZE;
printf("初始化成功!\n");
return OK;
}
//销毁
void DestroyList_Sq(SqList& L) {
if (L.elem)
delete L.elem;
}
//插入
Status ListInsert_Sq(SqList& L, int i, ElemType e) {
if (i<1 || i>L.length + 1) { //i值不合法
return ERROR;
printf("i值不合法\n");
}
if (L.length >= MAXSIZE) { //存储空间已满 增加分配
ElemType* newbase = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) { //存储分配失败
printf("存储分配失败!");
exit(OVERFLOW);
}
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
ElemType *q = &(L.elem[i - 1]);
for (ElemType* p = &(L.elem[L.length - 1]); q <= p; --p) {
*(p+1)=*p;
}
*q=e;
++L.length;
return OK;
}
//删除
Status ListDelete_Sq(SqList& L, int i, int& e) {
if (i<1 || i>L.length) { //i值不合法
printf("i值不合法!\n");
return ERROR;
}
ElemType* p = &(L.elem[i - 1]);
e = *p;
ElemType* q = L.elem + L.length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *p;
--L.length;
return OK;
}
//查找
int LocateElem_Sq(SqList L, ElemType e,int (*compare)(ElemType, ElemType)){
int i = 1;
ElemType* p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))
++i;
if (i <= L.length)
return i;
else return 0;
}
//比较
int compare(ElemType a,
ElemType b) {
if (a != b)
return 0;
else
return 1;
}
//求表长
int GetLength(SqList L) {
return L.length;
}
//判空
int IsEmpty(SqList L) {
if (L.length == 0)
return 1;
else
return 0;
}
//存取
int GetElem(SqList L, int i) {
if (i<1 || i>L.length)
return ERROR;
return L.elem[i - 1];
}
//打印
void ListPrint(SqList L) {
for (int i = 0; i < L.length; i++) {
printf("第%d个元素是%d\n", i + 1, L.elem[i]);
}
return;
}
main.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"sqlist.h"
void menu() {
printf("**********************************************\n");
printf("**1.创建 **2.初始化\n");
printf("**3.插入 **4.删除\n");
printf("**5.查找 **6.求表长\n");
printf("**7.存取 **8.判空\n");
printf("**9.打印 **0.销毁并退出\n");
printf("**********************************************\n");
}
int main() {
SqList L;
int temp,input;
menu();
do {
scanf("%d", &input);
switch (input) {
case 1:
SqList L;
printf("创建完成\n");
break;
case 2:
InitList_Sq(L);
break;
case 3:
int i;
ElemType e;
printf("请输入插入的位置和数值(i e):\n");
scanf("%d %d", &i, &e);
ListInsert_Sq(L, i, e);
break;
case 4:
int j;
ElemType f;
printf("请输入删除的位置(i):\n");
scanf("%d", &j);
ListDelete_Sq(L, j, f);
break;
case 5:
ElemType g;
printf("请输入需查找的元素e:\n");
scanf("%d", &g);
printf("元素%d位于线性表的第%d位\n", g, LocateElem_Sq(L, g, compare));
break;
case 6:
printf("表长为:%d\n", GetLength(L));
break;
case 7:
int k;
printf("请输入要存取的元素位置:");
scanf("%d", &k);
printf("第%d个元素是:%d\n",k, GetElem(L, k));
break;
case 8:
if (IsEmpty(L))
printf("表为空\n");
else
printf("表不为空\n");
break;
case 9:
ListPrint(L);
printf("打印结束\n\n");
break;
case 0:
DestroyList_Sq(L);
printf("顺序表已销毁!");
break;
default:printf("输入错误,请输入正确的指令:");
}
} while (input);
}
总结
1.线性表是通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系
2.顺序表的逻辑顺序与物理顺序一致,使用顺序表,可以实现随机存储