数据结构-C语言-线性表 || 顺序表的实现

顺序表的创建——初始化、插入、删除、查找操作

▍抽象数据结构的定义

▍代码

▍时间复杂度与空间复杂度分析

▍实验事例验证与分析


▍抽象数据结构的定义

ADT List{

数据对象:D={ai|ai∈ElemType,i=1,2…,n,n≥0}

数据关系:R1={<a(i-1),ai>| a(i-1),ai∈D,i=1,2…,n }

基本操作:

    InitList_Sq(&Z,len)

  操作结果:构造一个空的线性表,并初始化。

  ListInsert(&L,i,e0)

      初始条件:线性表已存在,且1≤i≤len+1。

      操作结果:在顺序表L中第i个位置之前插入新的元素e。

    ListDelete(&L,i)

      初始条件:线性表已存在且非空,且1≤i≤len。

      操作结果:删除顺序表L中第i个位置的元素并返回,L的长度减1。

FindList(L,e0)

      初始条件:线性表已存在。

              操作结果:(按值查找)查找顺序表中第一个出现的该元素并定位,返回该值        所在的位置序号。

}ADT List

▍代码

//Sqlist.h
#pragma once

//exit(0)           正常运行并退出程序   
//exit(1)  exit(-1) 非正常运行导致程序退出
#define OVERFLOW -1         //状态量:存储分配失败,结束进程
#define OK 0                //状态量:存储分配成功,即完成初始化
#define ERROR 1             //状态量:输入不合法,出现错误,结束进程

typedef int Status;      //定义返回状态
typedef float ElemType;  //帮助定义顺序表中元素的数据类型
typedef int Length;      //帮助定义顺序表的长度

typedef struct {
	ElemType* e;       //存储空间的基地址
	Length len;        //当前顺序表长度
	Length Listsize;   //分配的存储容量——总长度
}Sqlist;

Status InitList_Sq(Sqlist& L, Length len);  //对顺序表进行初始化
Status ListInsert(Sqlist* L, int i, ElemType e0);    //将某个数据元素插入到顺序表中
ElemType ListDelete(Sqlist* L, int i);              //对顺序表内的某一数据元素实行删除操作
Length Findlist(Sqlist* L, ElemType e0);     //对顺序表进行查找
void Print(Sqlist* L);          //对顺序表进行输出



//list.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Sqlist.h"
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

#define LIST_INIT_SIZE 100  //顺序表初始长度
#define LIST_INCREMENT 10   //顺序表的分配增量——扩增容量
ElemType* q;                //q为插入元素所在位置
ElemType* p;                //p表示元素所在位置

//初始化操作
Status InitList_Sq(Sqlist& L,Length len){
	L.e = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));  //先使用malloc函数给线性表分配初始空间
	if (!L.e) {
		printf("[warning]--OVERFLOW!  please run again-");
		exit(OVERFLOW);            //存储分配失败提示,结束进程
	}
//存储空间分配成功后
	L.len = 0;                    //定义空表长度为0
	L.Listsize = LIST_INIT_SIZE;    //定义初始存储容量为100
	
	printf("请输入浮点型数据元素(空格隔开即可):");
	for (int j = 0; j < len; j++)  //逐个输入数据元素
		scanf("%f", &L.e[j]);
	L.len += len;                  //输入完毕后顺序表的长度
	return OK;                     //初始化顺序表已完成
}

//插入一位元素的操作-在顺序表L中第i个位置之前插入新的元素e
Status ListInsert(Sqlist* L, int i, ElemType e0) {
	if (i<1 || i>=L->len + 1)   //判断第i个位置是否合法
		return ERROR;

	//判断存储容量是否足够(如果成立,则当前存储容量已满,需要扩容
	if (L->len >= L->Listsize) {
		L->e = (ElemType*)realloc(L->e, (L->Listsize + LIST_INCREMENT) * sizeof(ElemType));  //realloc函数进行扩容操作
		if (!L->e) {  //为防止内存泄漏,需要判断(如果泄露则结束进程)
			printf("[warning]--OVERFLOW!  please run again-");
			exit(OVERFLOW);            //存储分配失败提示,结束进程
		}
		L->Listsize += LIST_INCREMENT; //更新存储容量
	}
	
	q = &(L->e[i - 1]);  //q为插入元素所在位置
	for (p = &(L->e[L->len - 1]); p >= q; --p) {
		*(p + 1) = *p;  //把插入元素和其后的元素后移一位
	}
	*q = e0;   //q位置放入插入的元素
	++L->len;  //顺序表长度增加1位
	return OK;
}

//删除一位元素的操作-删除顺序表L中第i个位置的元素并返回
ElemType ListDelete(Sqlist* L, int i) {
	if (i<1 || i>L->len)  //判断第i个位置是否合法(1~n)
		return ERROR;
	p = &(L->e[i-1]);   //第i个元素的位置
	ElemType e1 = *p;     //接收第i个元素并返回
	q = &(L->e[L->len - 1]);  //倒数第1个元素地址
	for (; p < q; ++p) {
		*p = *(p + 1);    //把删除元素之后的元素前移
	}
	--L->len;
	return e1;
}

//查找顺序表中第一个出现的该元素并定位
Length Findlist(Sqlist* L,ElemType e0) {
	for (int i = 0; i < L->len; i++) {
		if (L->e[i] == e0)
			return i + 1;
	}
	return 0;
}

//输出顺序表
void Print(Sqlist* L) {
	printf("浮点型顺序表可展示为:");
	for (int i = 0; i < L->len; i++) {
		printf("%6.4f  ", L->e[i]); //cout << L->e[i] << " ";
	}
	printf("\n\n");
}

//界面优化函数
void interface() {
	printf("        “查找”请输入1\n        “插入”请输入2\n        “删除”请输入3\n        “退出”请输入4\n");
}

int main() {
	Sqlist L;  //构建一个顺序表
	ElemType e; //元素值——存放插入元素、查找元素、删除元素
	Length len; //顺序表的长度
	int ii = 0;  //进行删除、查找、插入元素的序号
	string c;  //操作选择:1-查找 2-插入 3-删除 4-退出

	//界面优化
	printf("——Welcome to our linear list——\n");
	printf("【已初始化】正在创建中,请输入创建的数据元素个数(len<101):len=");
	scanf("%d", &len);
	InitList_Sq(L, len);  //初始化顺序表-给顺序表分配空间
	Print(&L);     //输出初始化好的顺序表
	interface();  //界面优化函数
	printf("--please enter your choice:");
	cin >> c;

	do {
		//错误输入提示,可重新输入
		if (c != "1" && c != "2" && c != "3" && c != "4") { 
			printf("[warning]WRONG input,please enter again:");
			cin >> c;
		}
		//查找元素的操作(按序号查找)
		if (c == "1") {
			printf("请输入要查找的元素值 e=");
			scanf("%f", &e);
			ii = Findlist(&L, e);
			if (ii) {
				printf("查找元素的位置在第%d位", ii);
			}
			else {
				printf("[warning]查找元素不存在!");
			}
		}
		//插入元素的操作(按序号插入)
		else if (c == "2") {
			printf("请输入想要插入元素所在的序号(1≤i≤%d):i=", len);
			scanf("%d", &ii);
			if(ii >= 1 && ii <= len) {
				printf("请输入想要插入的数据元素值(请输入浮点数):e=");
				scanf("%f", &e);
				ListInsert(&L, ii, e);
				printf("——插入完成!\n");
				Print(&L);
			}
			else {
				printf("[warning]Insert out of range!");
			}
		}
		//删除元素操作
		else if (c == "3") {
			printf("请输入要删除的元素所在序号 i=");
			scanf("%d", &ii);  
			e = ListDelete(&L, ii);
			if (e == ERROR) {
				puts("[warning]Delete out of range!");
			}
			else {
				printf("——删除完成!删除的元素是:%6.4lf\n", e);
				Print(&L);
			}
		}
		else if (c == "4")break;
		printf("\n———--please enter your choice again:");
		cin >> c;
	} while (c == "1" || c == "2" || c == "3");
	return 0;
}

▍时间复杂度与空间复杂度分析

  • 元素的查找(FindList)

在按值查找的函数中,算法的时间耗费在比较数据元素上,删除元素的位置共有n个且是等可能的,即p=1/n,而需要查找 i 个元素。

则语句频度为∑p×i (1≤i≤n) =(n+1)/2

则算法的时间复杂度为O(n);在查找时,内存空间并没有发生变化,所以算法的空间复杂读为O(1)

  • 元素的插入(ListInsert)

ListInsert函数中,最基本的操作是for循环中的语句,也就是移位操作,输入想要插入的第i个位置,那么有n-i+1个元素需要发生移动,而i的取值在1~n之间,那么i是1~n之间的概率是等可能的,都为p=1/n,则

语句频度为∑p×(n-i+1)  (1≤i≤n) =(n+1)/2

则算法的时间复杂度为O(n);又因为每次移动都动态申请内存空间变化,所以算法的空间复杂读也为O(n)

  • 元素的删除(ListDelete)

与插入操作相同,最基本的操作是移位操作

改变的是有n-i 个元素需要发生移动

(而i的取值在1~n之间,那么i是1~n之间的概率是等可能的,都为p=1/n)则语句频度为∑p×(n-i)  (1≤i≤n) =(n-1)/2

则算法的时间复杂度为O(n);又因为每次移动都动态申请内存空间变化,所以算法的空间复杂读也为O(n)

▍实验事例验证与分析

①首先选择输入的数据元素个数len=2;

②其次输入len=2个浮点型数据 1.2 1.3 ,回车可以看到顺序表展示以及需要进行的操作;

③进入操作页面:操作选择:1-查找 2-插入 3-删除 4-退出

a)选择查找功能:此时输入1.2和1.200没有影响

如果输入其他没有输入的数据,则会提示该数据元素不存在:

b)选择插入功能:提示给出有序号范围

如果超出元素个数的序号,会提示超出范围

c)选择删除功能:删除刚刚插入的元素1.345

如果输入序号超出元素个数,会提示超出范围

d)退出操作页面

      直接输入4即可退出程序,如下图是一系列操作。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值