基础数据结构之顺序表

一、 数据结构的基本概念

1.以下基本概念截图来自大话数据结构

在这里插入图片描述
在这里插入图片描述

数据项是数据不可分割的最小数据单位
在这里插入图片描述

2.关于逻辑结构和物理结构

逻辑结构:数据与数据关系的抽象关系,与物理地址无关
物理结构(存储结构):数据与数据之间,它在存储器中的存放方式
逻辑结构的分类:集合、线性、树形结构、图形结构、
物理结构的分类:顺序存储结构、链式存储结构

3.时间复杂度、空间复杂度

时间复杂度:算法中基本操作执行次数和问题规模n之间的关系,一般记为O(f(n))

例题:

//在计算时间复杂度的时候,记住 只要最高项,不要系数
//1    O(n)
for(int i=1; i<=n; i++)
{
	tmp += arr[i];
}

//2.  O(n^2)
for(int i=1; i<=n; i++)
{
	for(int j=1; j<=n; j++)
	{
		arr[i][j] = 1;//基本操作语句
	}
}

//3  O(1)
{
	++x;
	s=0;
}

//4  O(n)
for(int i=1; i<=n; i++) 
{
	++x;
	s+=x;
}

//5  O(n^2)
for(int i=2; i<=n; i++)
{
	for(int j=2; j<=i-1; ++j)
	{
		++x;
		arr[i][j] = x;//基本执行语句
	}
}

空间复杂度:算法中需要额外辅助空间和问题规模n之间的关系,一般记为O(f(n))
例题:(递归)

//递归中开辟的空间不会随着函数调用而消失
//递归里面的空间复杂度 O(n)
int Fun(int n)  //调用了n次函数,开辟了n次空间
{
	if(n<=1)
		return n;
	else
		return Fun(n-1)+1;
}

4.关于线性表的概念

线性表:有且只有一个开始结点,有且只有一个结束结点,并且除了开始结点外,其余结点都有直接前驱,并且除了结束结点外,其余结点都有直接后继,表示为:{a1,a2,a3,…an-1,an}
简而言之,逻辑关系是一对一的,例如:线性表,栈和队列,字符串,数组…

线性表按照其存储方式有两种
顺序表:数据结点间,物理相邻,逻辑也相邻
链表:数据结点间,逻辑相邻,物理不一定相邻

二、顺序表

将逻辑上相邻的数据元素,存储在物理上也相邻的存储单元中

1.用代码的方式实现顺序表

.h头文件定义结构体以及函数

#pragma once

#define LISTINCREMENT 100  //初始大小
#define LIST_INIT_SIZE 10   //不需要

//可扩容顺序表结构体设计

typedef int ELEM_TYPE;
typedef struct Sqlist {

	ELEM_TYPE* elem; //存储空间基址(用来接受malloc返回在堆上申请的连续空间块开辟地址)
	int length;  //当前有效长度
	int listsize ;  //当前总空间大小(以格子数为单位)

}Sqlist,*PSqlist;

//关于数据结构的操作,无外乎就是增删改查

//初始化
void Init_Sqlist(struct Sqlist* sq);

//头插
bool Insert_head(struct Sqlist* sq, ELEM_TYPE val);

//尾插
bool Insert_tail(struct Sqlist* sq, ELEM_TYPE val);

//换位置插
bool Insert_pos(struct Sqlist* sq, int pos, ELEM_TYPE val);

//头删
bool Del_head(struct Sqlist* sq);

//尾删
bool Del_tail(struct Sqlist* sq);

//按位置删
bool Del_pos(struct Sqlist* sq, int pos);

//按值删(找出这个值在顺序表中第一次出现的位置,然后删除)
bool Del_val(struct Sqlist* sq, ELEM_TYPE val);

//判空
bool Isempty(struct Sqlist* sq);

//判满
bool Isfull(struct Sqlist* sq);

//扩容函数
void Inc(struct Sqlist* sq);

//查找(找这个值在顺序表中,第一次出现的位置)
int Search(struct Sqlist* sq, ELEM_TYPE val);

//清空
void Clear(struct Sqlist* sq);

//销毁(将数据空间都释放掉)
void Destory(struct Sqlist* sq);

//打印
void Show(struct Sqlist* sq);

.cpp文件里面实现函数

#include<stdio.h>
#include"Sqlist.h"
#include<stdlib.h>
#include <cassert>

//初始化
void Init_Sqlist(struct Sqlist* sq) {
	sq->elem = (ELEM_TYPE*)malloc(LISTINCREMENT * sizeof(int));
	assert(sq->elem != NULL);
	sq->length = 0;
	sq->listsize = LISTINCREMENT;
}

//头插
bool Insert_head(struct Sqlist* sq, ELEM_TYPE val) {
	assert(sq != NULL);
	if (Isfull(sq)) {
		Inc(sq);
	 }
	else {
		for (int i = sq->length - 1; i >=0; i--) {
			sq->elem[i + 1] = sq->elem[i];
		}
		sq->elem[0] = val;
		sq->length++;
	}
	return true;
}

//尾插
bool Insert_tail(struct Sqlist* sq, ELEM_TYPE val){
	if (Isfull(sq)) {
		Inc(sq);
	}
	else {
		sq->elem[sq->length] = val;
		sq->length++;
	}
	return true;

}

//按位置插
bool Insert_pos(struct Sqlist* sq, int pos, ELEM_TYPE val) {
	if (Isfull(sq)) {
		Inc(sq);
	}
	else {
		for (int i = sq->length - 1; i >= pos; i--) {
			sq->elem[i+1] = sq->elem[i];
		}
		sq->elem[pos] = val;
		sq->length++;
	}
	return true;
}

//头删
bool Del_head(struct Sqlist* sq) {
	assert(sq != NULL);
	if (Isempty(sq)) {
		return false;
	}
	else {
		for (int i = 0; i < sq->length - 1; i++) {
			sq->elem[i] = sq->elem[i + 1];
		}
		sq->length--;
	}
	return true;
}

//尾删
bool Del_tail(struct Sqlist* sq) {
	
	//1.安全性处理(判断sq指针不指向空)
	assert(sq != NULL);
	
	//2.判空(判断sq指向的是否是一个空的顺序表)
	assert(sq->elem != NULL);
	
	//3.删除
	if (Isempty(sq)) {
		return false;
	}
	else {
		sq->length--;
	}
	return true;
}

//按位置删
bool Del_pos(struct Sqlist* sq, int pos) {

	//1.安全性处理(判断sq指针不指向空)
	assert(sq != NULL);

	//2.判空(判断sq指向的是否是一个空的顺序表)
	assert(sq->elem != NULL);

	//3.pos的合法性,pos默认为0时,为头删
	assert(pos >= 0 && pos < sq->length);

	if (Isempty(sq)) {
		return false;
	}
	else {
		for (int i = pos; i < sq->length - 1; i++) {
			sq->elem[i] = sq->elem[i + 1];
		}
		sq->length--;
	}
	return true;
}

//按值删(找出这个值在顺序表中第一次出现的位置,然后删除)
bool Del_val(struct Sqlist* sq, ELEM_TYPE val) {
	
	assert(sq != NULL);

	//直接调用其它函数
	int temp = Search(sq, val);
	if (temp == -1) {
		return false;
	}
	else {
		return Del_pos(sq, temp);
	}

}

//判空
bool Isempty(struct Sqlist* sq) {
	assert(sq != NULL);
	if (sq->length == 0) {
		return true;
	}
	return false;
}

//判满
bool Isfull(struct Sqlist* sq) {
	assert(sq != NULL);
	if (sq->length == sq->listsize) {
		return true;
	}
	return false;
}

//扩容函数  按2倍扩容
void Inc(struct Sqlist* sq) {

	sq->elem=(ELEM_TYPE*)realloc(sq->elem,(sq->listsize * sizeof(int))*2);
	assert(sq->elem != NULL);
	sq->listsize *= 2;
}

//查找(找这个值在顺序表中,第一次出现的位置)
int Search(struct Sqlist* sq, ELEM_TYPE val) {
	for (int i = 0; i < sq->length - 1; i++) {
		if (sq->elem[i] == val) {
			return i;
		}
	}
	return -1;
}

//清空
void Clear(struct Sqlist* sq) {
	assert(sq != NULL);
	sq->length = 0;
}

//销毁(将数据空间都释放掉)
void Destory(struct Sqlist* sq) {
	free(sq->elem);
	sq->length = sq->listsize = 0;
}

//打印
void Show(struct Sqlist* sq) {
	for (int i = 0; i < sq->length; i++) {
		printf("%d", sq->elem[i]);
	}
	printf("\n");
}

.cpp在main函数里面测试代码

#include<stdio.h>
#include"Sqlist.h"
#include<stdlib.h>
#include <cassert>

int main() {
	struct Sqlist head;
	Init_Sqlist(&head);

	for (int i = 0; i < 100; i++) {
		Insert_pos(&head, i, i + 1);
	}
	Show(&head);

	return 0;
}

2.总结

顺序表的特点:

  1. 顺序表的操作需要挪动元素,插入的话,需要向后挪动,删除的话,需要向前覆盖,时间复杂度为O(n),效率不高
    但是,如果在尾部操作,则不需要挪动元素,效率极高,为O(1)
  2. 顺序表的使用场景:
    适合的场景:
    2.1支持直接访问
    2.2插入和删除操作,主要集中在尾部
    不适合的场景:
    在头部中间位置,插入和删除较多,频繁的扩容,扩容代价高
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
南京邮电大学数据结构课程中,顺序表是一个非常基础数据结构,其实现主要包括以下几个方面: 1. 顺序表的定义:顺序表是一种线性表,其特点是元素在物理空间上连续存储,逻辑上也是连续的。顺序表的定义可以使用数组来实现。 2. 顺序表的基本操作:包括初始化、插入、删除、查找、修改等操作。其中,插入和删除操作需要考虑到元素的移动问题。 3. 顺序表的组合应用:顺序表可以用来实现其他数据结构,例如栈、队列等。 下面是一个简单的Python代码示例,演示了如何实现顺序表的基本操作: ```python class SeqList: def __init__(self, maxsize=None): self.maxsize = maxsize self.array = [None] * self.maxsize self.length = 0 def __len__(self): return self.length def __getitem__(self, index): if index < self.length: return self.array[index] else: raise IndexError('Index out of range') def __setitem__(self, index, value): if index < self.length: self.array[index] = value else: raise IndexError('Index out of range') def insert(self, index, value): if self.length >= self.maxsize: raise Exception('SeqList is full') if index < 0 or index > self.length: raise IndexError('Index out of range') for i in range(self.length, index, -1): self.array[i] = self.array[i-1] self.array[index] = value self.length += 1 def delete(self, index): if index < 0 or index >= self.length: raise IndexError('Index out of range') for i in range(index, self.length-1): self.array[i] = self.array[i+1] self.length -= 1 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值