【数据结构】顺序表实例探究

news2024/11/19 7:31:19

💗个人主页💗
⭐个人专栏——数据结构学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

  • 导读:
  • 1. 顺序表的基本内容
    • 1.1 概念及结构
    • 1.2 时间和空间复杂度
    • 1.3 基本操作
    • 1.4 顺序表的优缺点
  • 2. 静态顺序表
  • 3. 动态顺序表
  • 4. 实现动态顺序表。
    • 4.1 定义结构体
    • 4.2 顺序表初始化
    • 4.3 顺序表打印
    • 4.4 顺序表销毁
    • 4.5 顺序表容量检查
    • 4.6 顺序表尾插
    • 4.7 顺序表头插
    • 4.8 顺序表尾删
    • 4.9 顺序表头删
    • 4.10 顺序表在任意位置插入数据
    • 4.11 顺序表删除任意位置数据
    • 4.12 顺序表查找数据
  • 5. 所有代码整理
    • 5.1 SeqList.h头文件
    • 5.2 SeqList.c 函数定义
    • 5.3 study.c 主函数调用测试

导读:

我们在前面学习了很多C语言的知识,更多C语言内容点击:C语言初步学习专栏
今天我们就进一步的学习数据结构——顺序表,含有实例讲解

1. 顺序表的基本内容

1.1 概念及结构

顺序表是一种基本的线性结构,其元素在内存中是连续存储的。
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

1.2 时间和空间复杂度

在顺序表中,每个元素都在其前面一个元素的位置之后,后面一个元素的位置之前。顺序表可以通过下标随机访问和修改元素,其时间复杂度为O(1)。在插入或删除元素时,需要移动其他元素的位置,时间复杂度为O(n)。

1.3 基本操作

  1. 初始化:创建一个指定大小的空顺序表
  2. 插入元素:在指定位置插入一个元素,需要移动其他元素的位置
  3. 删除元素:删除指定位置的元素,需要移动其他元素的位置
  4. 查找元素:根据下标查找指定位置的元素
  5. 修改元素:根据下标修改指定位置的元素

1.4 顺序表的优缺点

优点:

  1. 随机访问和修改元素的时间复杂度为O(1)
  2. 内存空间利用率高,不会浪费过多空间
  3. 适合存储元素数量不太多且需要随机访问元素的场景

缺点:

  1. 插入和删除元素的时间复杂度为O(n),在元素数量较大时会影响性能
  2. 顺序表长度固定,无法动态增加或缩小容量
  3. 在插入或删除元素时,需要移动其他元素的位置,容易出错

2. 静态顺序表

静态顺序表,也称为静态数组实现的顺序表,是一种用数组实现的顺序表。其特点是存储空间固定,一旦分配后,大小就不再改变。
优点:

  1. 访问元素的速度快,因为数组支持随机访问,可以通过下标直接访问指定位置的元素。
  2. 使用数组存储元素,静态顺序表的数据存储形式比较简单,容易实现。

缺点:

  1. 存储空间固定,一旦分配后就不能改变大小,如果需要存储的元素数量超过预先分配的空间大小,就会出现溢出的情况。
  2. 如果要在表中插入或删除元素,就需要移动其他元素,操作比较繁琐。

3. 动态顺序表

使用动态开辟的数组存储。
动态顺序表,也称为动态数组实现的顺序表,是一种根据需要动态调整存储空间大小的顺序表,可以在需要时自动扩展或缩小存储空间。
优点:

  1. 可以根据实际需求动态调整存储空间大小,不会出现溢出的情况。
  2. 使用数组存储元素,访问元素的速度快,可以通过下标直接访问指定位置的元素。

缺点:

  1. 需要进行动态内存管理,实现起来相对比较复杂。
  2. 在动态扩展存储空间时,需要重新分配更大的内存空间,并将原有数据拷贝到新的内存空间,比较耗费时间和空间。
  3. 在缩小存储空间时,可能会浪费部分内存空间

在这里插入图片描述

4. 实现动态顺序表。

我们需要创建两个 C文件: study.c 和 SeqList.c,以及一个 头文件: SeqList.h。
头文件来声明函数,一个C文件来定义函数,另外一个C文件来用于主函数main()进行测试。

4.1 定义结构体

typedef是类型定义的意思。typedef struct 是为了使用这个结构体方便。

若struct SeqList {}这样来定义结构体的话。在申请SeqList 的变量时,需要这样写,struct SeqList n;
若用typedef,可以这样写,typedef struct SeqList{}SL; 。在申请变量时就可以这样写,SL n;
区别就在于使用时,是否可以省去struct这个关键字。

SeqList.h:

//给int类型起一个别名——SLDataType
typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{
	SLDataType * a;	//指向动态开辟的数组
	int size;		//有效数据
	int capacity;	//空间容量
}SL;

4.2 顺序表初始化

study.c调用

//用来测试函数
void TestSL1()
{
	SL sl;//定义结构体变量
	SLInit(&sl);//调用初始化函数并传址
}

int main()
{
	TestSL1();
	return 0;
}

SeqList.h声明函数

void SLInit(SL *psl);//SL *psl接收sl的地址

SeqList.c定义函数

// 顺序表初始化
void SLInit(SL *psl)
{
	assert(psl);//断言psl是否为空
	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

4.3 顺序表打印

SeqList.h声明函数

// 顺序表打印
void SLPrint(SL* psl);

SeqList.c定义函数

// 顺序表打印
void SLPrint(SL* psl)
{
	assert(psl);
	//通过指针对结构体内size解引用操作
	//size代表有效数据个数,则循环size次,一一打印数据
	for (int i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->a[i]);
	}
	printf("\n");
}

study.c调用

void TestSL1()
{
	SL sl;
	SLInit(&sl);
	SLPrint(&sl);
}
int main()
{
	TestSL1();
	return 0;
}

4.4 顺序表销毁

动态内存空间开辟,使用完之后需要进行销毁。
SeqList.h声明函数

// 顺序表销毁
void SLDestroy(SL *psl);

SeqList.c定义函数

void SLDestroy(SL* psl)
{
	assert(psl);
	//判断是否开辟了动态内存
	if (psl->a != NULL)
	{
		//开辟了则释放
		free(psl->a);
		psl->a = NULL;
		psl->size = 0;
		psl->capacity = 0;
	}
}

study.c调用

void TestSL1()
{
	SL sl;
	SLInit(&sl);
	SLPrint(&sl);
	SLDestroy(&sl);
}
int main()
{
	TestSL1();
	return 0;
}

4.5 顺序表容量检查

在对顺序表进行头插和尾插数据时,要先检查容量是否足够。
SeqList.h声明函数

// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl);

SeqList.c定义函数

// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{
	assert(psl);
	//如果size有效数据个数与数组总容量相等,则要进行增容
	if (psl->size == psl->capacity)
	{
		//如果总容量为0,则开辟4个空间,否则就开辟原来容量的二倍
		int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		//定义tmp指针,指向新开辟的空间
		SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newCapacity);
		//开辟失败,返回错误信息
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		//如果开辟成功则重新赋给原来的数组指针
		psl->a = tmp;
		psl->capacity = newCapacity;
	}
}

4.6 顺序表尾插

尾插就是在顺序表尾端添加数据。我们在主文件中调用尾插函数和打印以及销毁函数,测试代码是否能正常运行。
SeqList.h声明函数

// 顺序表尾插
void SLPushBack(SL* psl, SLDataType x);

SeqList.c定义函数

// 顺序表尾插
void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);
	//进行尾插时需要检查空间是否够用
	SLCheckCapacity(psl);
	//将想要插入的数据赋值给下标为size的元素
	psl->a[psl->size] = x;
	//size加一,代表有效数据个数增加
	psl->size++;
}

在这里插入图片描述

study.c调用

void TestSL1()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPrint(&sl);
	
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	
	SLPrint(&sl);
	SLDestroy(&sl);
}

int main()
{
	TestSL1();
	return 0;
}

在这里插入图片描述

4.7 顺序表头插

在顺序表的头部插入数据。
该怎么做呢?
我们可以把所有的有效数据都往后移一位,就可以把想要插入的数据赋给我们的下标为1的元素。

TestSL()函数是用来测试的,但是如果我们所有的东西都在一个函数里测试,可能会出现出错但是不能及时找到的问题,或者是当时有bug但是没有显示,到后面影响到其它代码,所有我们可以多定义几个像TestSL()这样的函数用来测试我们不同的功能,在main()函数里调用即可。
头部插入数据我们就在TestSL2()函数里来进行测试。

SeqList.h声明函数

void SLPushFront(SL* psl, SLDataType x);

SeqList.c定义函数

void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);
	//头插之前先检查容量
	SLCheckCapacity(psl);
	//end代表最后一个数组元素的小标
	int end = psl->size - 1;
	//进入while循环实现把前一个元素赋值给后面的元素
	while (end >= 0)
	{

		psl->a[end + 1] = psl->a[end];
		--end;
	}
	//把数据赋值给第一个下标指向的空间
	psl->a[0] = x;
	//size++,记录有效元素个数增加
	psl->size++;
}

在这里插入图片描述

study.c调用

void TestSL2()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPushFront(&sl, 10);
	SLPushFront(&sl, 20);
	SLPushFront(&sl, 30);
	SLPushFront(&sl, 40);

	SLPrint(&sl);
	SLDestroy(&sl);
}

int main()
{
	TestSL2();
	return 0;
}

在这里插入图片描述

4.8 顺序表尾删

把数组最后一个有效数据删除。
直接删除最后一个下标元素即可,也就是让有效数据减一。
TestSL3()函数测试尾删。

SeqList.h声明函数

//顺序表尾删
void SLPopBack(SL* psl);

SeqList.c定义函数

//直接删除最后一个下标元素即可
void SLPopBack(SL* psl)
{
	assert(psl);
	//暴力检查,判断是否为空数据
	assert(psl->size > 0);
	//直接让size--,有效数据减一即可
	psl->size--;
}

在这里插入图片描述

study.c调用

void TestSL3()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPopBack(&sl);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPrint(&sl);

	SLDestroy(&sl);
}
int main()
{
	TestSL3();
	return 0;
}

在这里插入图片描述

4.9 顺序表头删

把第一个数据删除,也就是所有数据往前移动,再让size–(有效数据减一)。
TestSL3()函数测试头删。

SeqList.h声明函数

// 顺序表头删
void SLPopFront(SL* psl);

SeqList.c定义函数

// 顺序表头删
void SLPopFront(SL* psl)
{
	assert(psl);

	//暴力检查
	assert(psl->size > 0);
	//记录第二个元素的下标
	int begin = 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		//把后面的元素赋值给前一个
		++begin;
	}
	//有效数据个数自减1
	psl->size--;
}

在这里插入图片描述

study.c调用

//头删测试
void TestSL4()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPrint(&sl);

	SLDestroy(&sl);

}
int main()
{
	TestSL1();
	return 0;
}

在这里插入图片描述

4.10 顺序表在任意位置插入数据

思路和头插相差无几,找到pos下标指向位置,把其后所有数据往后移,再让x进行覆盖即可。

SeqList.h声明函数

// 顺序表在pos(任意)位置插入x
void SLInsert(SL* psl, int pos, SLDataType x);

SeqList.c定义函数

//注意pos是下标
//size是数据个数,看作下标的话,他是最后一个书的下标
void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	//判定想要插入的位置是否属于有效空间
	assert(pos >= 0 && pos <= psl->size);
	//判断空间是否充足
	SLCheckCapacity(psl);

	//挪动数据
	//end记录倒数第二个元素下标
	int end = psl->size - 1;
	//把数据从后往前依次往后移动,到pos位置结束
	while (end >= pos)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}
	//把x赋值给下标为pos的元素
	psl->a[pos] = x;
	//有效数据个数自加1
	psl->size++;
}

在这里插入图片描述

study.c调用

void TestSL5()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLInsert(&sl, 2, 20);
	SLPrint(&sl);

	SLInsert(&sl, 3, 40);
	SLInsert(&sl, 4, 9);
	SLPrint(&sl);

	SLDestroy(&sl);
}
int main()
{
	TestSL5();
	return 0;
}

在这里插入图片描述

4.11 顺序表删除任意位置数据

从pos位置开始,让后面的数据对前面的数据进行覆盖。
SeqList.h声明函数

// 顺序表删除pos(任意)位置的值
void SLErase(SL* psl, int pos);

SeqList.c定义函数

void SLErase(SL* psl, int pos)
{
	assert(psl);
	//判定想要删除的位置是否属于有效空间
	assert(pos >= 0 && pos < psl->size);
	
	//从pos位置开始,让后面的数据对前面的数据进行覆盖
	int begin = pos + 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		++begin;
	}
	//有效数据个数自减1
	psl->size--;

}

在这里插入图片描述

study.c调用

void TestSL6()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLErase(&sl, 3);
	SLPrint(&sl);

	SLErase(&sl, 1);
	SLPrint(&sl);

	SLDestroy(&sl);
}

int main()
{
	TestSL1();
	return 0;
}

在这里插入图片描述

4.12 顺序表查找数据

在顺序表中查找是否有x这个值,有则返回所在下标,没有返回-1 。
我们在这里设定,查找顺序表内是否存在x这个数据,有则删除。
SeqList.h声明函数

//顺序表查找
int SLFind(SL* psl, SLDataType x);

SeqList.c定义函数

int SLFind(SL* psl, SLDataType x)
{
	assert(psl);
	//循环整个有效数据,在其中一一判断
	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

study.c调用

//顺序表查找测试
void TestSL7()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);
	
	int pos = SLFind(&sl, 2);
	if (pos != -1)
	{
		SLErase(&sl, pos);
	}
	SLPrint(&sl);
	SLDestroy(&sl);
}

int main()
{
	TestSL1();
	return 0;
}

在这里插入图片描述

5. 所有代码整理

5.1 SeqList.h头文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//把int类型重命名为SLDataType
typedef int SLDataType;
//typedef是类型定义的意思。
//typedef struct 是为了使用这个结构体方便。
//若struct node{}这样来定义结构体的话。
//在申请node 的变量时,需要这样写,struct node n;

typedef struct SeqList
{
	SLDataType * a;	//指向动态开辟的数组
	int size;		//有效数据
	int capacity;	//空间容量
}SL;

// 基本增删查改接口
// 顺序表初始化
void SLInit(SL *psl);
// 顺序表销毁
void SLDestroy(SL *psl);
// 顺序表打印
void SLPrint(SL* psl);
// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl);


//头尾插入删除
// 顺序表尾插
void SLPushBack(SL* psl, SLDataType x);
// 顺序表头插
void SLPushFront(SL* psl, SLDataType x);
//顺序表尾删
void SLPopBack(SL* psl);
// 顺序表头删
void SLPopFront(SL* psl);

// 顺序表在pos(任意)位置插入x
void SLInsert(SL* psl, int pos, SLDataType x);
// 顺序表删除pos(任意)位置的值
void SLErase(SL* psl, int pos);
//顺序表查找
int SLFind(SL* psl, SLDataType x);

5.2 SeqList.c 函数定义

#include "SeqList.h"

// 顺序表初始化
void SLInit(SL *psl)
{
	assert(psl);//断言
	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

// 顺序表销毁
//动态内存空间开辟,使用完之后需要进行销毁
void SLDestroy(SL* psl)
{
	assert(psl);
	//判断是否开辟了动态内存
	if (psl->a != NULL)
	{
		//开辟了则释放
		free(psl->a);
		psl->a = NULL;
		psl->size = 0;
		psl->capacity = 0;
	}
}

// 顺序表打印
void SLPrint(SL* psl)
{
	assert(psl);
	//通过指针对结构体内size解引用操作
	//size代表有效数据个数,则循环size次,一一打印数据
	for (int i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->a[i]);
	}
	printf("\n");
}

// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{
	assert(psl);
	//如果size有效数据个数与数组总容量相等,则要进行增容
	if (psl->size == psl->capacity)
	{
		//如果总容量为0,则开辟4个空间,否则就开辟原来容量的二倍
		int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		//定义tmp指针,指向新开辟的空间
		SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newCapacity);
		//开辟失败,返回错误信息
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		//如果开辟成功则重新赋给原来的数组指针
		psl->a = tmp;
		psl->capacity = newCapacity;
	}
}

// 顺序表尾插
void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);
	//进行尾插时需要检查空间是否够用
	SLCheckCapacity(psl);
	//将想要插入的数据赋值给下标为size的元素
	psl->a[psl->size] = x;
	//size加一,代表有效数据个数增加
	psl->size++;
}

// 顺序表头插
//头插的思路是先把所有数据往后移一位
//再把想要插入的数据赋值给第一个下标指向的空间
void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);
	//头插之前先检查容量
	SLCheckCapacity(psl);
	//end代表最后一个数组元素的小标
	int end = psl->size - 1;
	//进入while循环实现把前一个元素赋值给后面的元素
	while (end >= 0)
	{

		psl->a[end + 1] = psl->a[end];
		--end;
	}
	//把数据赋值给第一个下标指向的空间
	psl->a[0] = x;
	//size++,记录有效元素个数增加
	psl->size++;
}

// 顺序表尾删
//直接删除最后一个下标元素即可
void SLPopBack(SL* psl)
{
	assert(psl);

	//空
	/*if (psl->size == 0)
	{
		return;
	}*/
	//暴力检查,判断是否为空数据
	assert(psl->size > 0);

	//psl->a[psl->size - 1] = -1;
	//直接让size--,有效数据减一即可
	psl->size--;
}

// 顺序表头删
void SLPopFront(SL* psl)
{
	assert(psl);

	//暴力检查
	assert(psl->size > 0);
	//记录第二个元素的下标
	int begin = 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		//把后面的元素赋值给前一个
		++begin;
	}
	//有效数据个数自减1
	psl->size--;
}

//注意pos是下标
//size是数据个数,看作下标的话,他是最后一个书的下标
void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	//判定想要插入的位置是否属于有效空间
	assert(pos >= 0 && pos <= psl->size);
	SLCheckCapacity(psl);

	//挪动数据
	//end记录倒数第二个元素下标
	int end = psl->size - 1;
	//把数据从后往前依次往后移动,到pos位置结束
	while (end >= pos)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}
	//把x赋值给下标为pos的元素
	psl->a[pos] = x;
	//有效数据个数自加1
	psl->size++;
}


// 顺序表删除pos(任意)位置的值
void SLErase(SL* psl, int pos)
{
	assert(psl);
	//判定想要删除的位置是否属于有效空间
	assert(pos >= 0 && pos < psl->size);
	
	//从pos位置开始,让后面的数据对前面的数据进行覆盖
	int begin = pos + 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		++begin;
	}
	//有效数据个数自减1
	psl->size--;

}

//顺序表查找
int SLFind(SL* psl, SLDataType x)
{
	assert(psl);
	//循环整个有效数据,在其中一一判断
	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

5.3 study.c 主函数调用测试

#define _CRT_SECURE_NO_WARNINGS 
#include "SeqList.h"

//顺序表问题
//1. 尾部插入效率还不错,头部或中间插入删除,需要挪动数据,效率低下
//2. 满了以后只能扩容,扩容是有一定的消耗的
//扩容一般是存在一定的空间浪费
//(假设空间是100,扩容到200,只需要插入120个数据,有80个就浪费了)

//尾插测试
void TestSL1()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPrint(&sl);

	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);
	SLDestroy(&sl);
}

//头插测试
void TestSL2()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPushFront(&sl, 10);
	SLPushFront(&sl, 20);
	SLPushFront(&sl, 30);
	SLPushFront(&sl, 40);

	SLPrint(&sl);
	SLDestroy(&sl);
}

//尾删测试
void TestSL3()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPopBack(&sl);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPrint(&sl);

	SLDestroy(&sl);
}

//头删测试
void TestSL4()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPrint(&sl);

	SLDestroy(&sl);

}

//任插测试
void TestSL5()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLInsert(&sl, 2, 20);
	SLPrint(&sl);

	SLInsert(&sl, 3, 40);
	SLInsert(&sl, 4, 9);
	SLPrint(&sl);

	SLDestroy(&sl);
}


//任删测试
void TestSL6()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);

	SLPrint(&sl);

	SLErase(&sl, 3);
	SLPrint(&sl);

	SLErase(&sl, 1);
	SLPrint(&sl);

	SLDestroy(&sl);
}

//顺序表查找测试
void TestSL7()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);
	
	int pos = SLFind(&sl, 2);
	if (pos != -1)
	{
		SLErase(&sl, pos);
	}
	SLPrint(&sl);
	SLDestroy(&sl);
}


int main()
{
	//尾插测试
	//TestSL1();
	 
	//头插测试
	//TestSL2();
	
	//测试尾删
	//TestSL3();

	//头删测试
	//TestSL4();

	//pos测试
	//TestSL5();

	//任删测试
	//TestSL6();

	//顺序表查找测试
	TestSL7();
	return 0;
}



//合并两个有序数组
//给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,
//分别表示 nums1 和 nums2 中的元素数目。
//
//请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
//void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
//	int i1 = m - 1;//记录第一个数组的下标
//	int i2 = n - 1;//记录第二个数组的下标
//	int j = m + n - 1;//记录总数组最后的下标
//	while (i1 >= 0 && i2 >= 0)
//	{
//		if (nums1[i1] > nums2[i2])
//		{
//			nums1[j--] = nums1[i1--];
//		}
//		else
//		{
//			nums1[j--] = nums2[i2--];
//		}
//	}
//	while (i2 >= 0)
//	{
//		nums1[j--] = nums2[i2--];
//	}
//}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1155302.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CVPR 2023 | 主干网络FasterNet 核心解读 代码分析

本文分享来自CVPR 2023的论文&#xff0c;提出了一种快速的主干网络&#xff0c;名为FasterNet。 论文提出了一种新的卷积算子&#xff0c;partial convolution&#xff0c;部分卷积(PConv)&#xff0c;通过减少冗余计算和内存访问来更有效地提取空间特征。 创新在于部分卷积…

xhadmin多应用SaaS框架怎么更新?

xhadmin是什么&#xff1f; xhadmin 是一套基于最新技术的研发的多应用 Saas 框架&#xff0c;支持在线升级和安装模块及模板&#xff0c;拥有良好的开发框架、成熟稳定的技术解决方案、提供丰富的扩展功能。为开发者赋能&#xff0c;助力企业发展、国家富强&#xff0c;致力于…

【设计模式】第13节:结构型模式之“享元模式”

一、简介 所谓“享元”&#xff0c;顾名思义就是被共享的单元。享元模式的意图是复用对象&#xff0c;节省内存&#xff0c;前提是享元对象是不可变对象。 实现&#xff1a;通过工厂模式&#xff0c;在工厂类中&#xff0c;通过一个Map或者List来缓存已经创建好的享元对象&am…

这样的软件测试报告模板你绝对没见过!!!

测试报告如此重要&#xff0c;那么我们应该如何撰写呢&#xff1f;为了让大家彻底掌握测试模板的撰写&#xff0c;所以本文结构如下&#xff1a; 1、测试报告写给谁看&#xff1f; 2、测试报告的基本骨架&#xff08;通过|不通过&#xff09;&#xff1f; 3、测试报告如何才能达…

超级搜索技术,普通人变强的唯一外挂

搜索效率&#xff1a;Google >微信公众号 >短视频 >百度 1、信息咨询搜索 在Google搜索栏前面加上 “” 限定关键词 intitle 限定标题 allintitle 限定标题多个关键词 intext 限定内容关键词 inurl 限定网址关键词 site 限定网址来源 imagesize 限定图片尺寸 filet…

[LeetCode]-27. 移除元素-26.删除有序数组中的重复项-88.合并两个有序数组

目录 27.移除元素 题目 思路 代码 26. 删除有序数组中的重复项 题目 思路 代码 88.合并两个有序数组 题目 思路 代码 总结 27.移除元素 27. 移除元素 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/remove-element/description/ 题目 给你一…

【快报】正在把教学视频搬运到B站和油管

hello 大家好&#xff0c;我是老戴。 熟悉我的同学知道&#xff0c;我从14年开始录制GIS相关的教学视频&#xff0c;之前是放到优酷上给大家下载&#xff0c;后期发现很多人把视频弄下来淘宝上卖&#xff0c;然后我就把视频整体放到了我自己的网站上。 随着视频录制的数量越来…

C++归并排序算法的应用:计算右侧小于当前元素的个数

题目 给你一个整数数组 nums &#xff0c;按要求返回一个新数组 counts 。数组 counts 有该性质&#xff1a; counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。 示例 1&#xff1a; 输入&#xff1a;nums [5,2,6,1] 输出&#xff1a;[2,1,1,0] 解释&#xff1a; 5 …

2024年湖北武汉建筑企业三类人员安全员ABC怎么报考

2024年湖北武汉建筑企业三类人员安全员ABC怎么报考 武汉建筑企业报考三类人员&#xff0c;建筑单位归属地在武汉&#xff0c;且有建筑相关的一些资Z&#xff0c;才可以申报一定数量的三类人员、安全员ABC、建筑安全员ABC、专职安全员C证、建设厅安全员ABC证。 建筑企业-报考建…

在线开发平台是什么?有哪些优势?

目录 一、什么是在线开发平台&#xff1f; 二、企业为什么选择在线开发平台&#xff1f; &#xff08;1&#xff09;风险低&#xff0c;回报高 &#xff08;2&#xff09;可视化操作更形象 &#xff08;3&#xff09;易维护 三、在线开发平台功能展示 技术介绍 随着互联网和信息…

Jetpack:024-Jetpack中的滚动事件

文章目录 1. 概念介绍2. 使用方法2.1 高级事件2.2 低级事件 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中事件相关的内容&#xff0c;本章回中主要 介绍事件中的滚动事件。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我们在…

三相马达的电机故障维护

目录 电机故障维护​编辑 更换电机操作 三相电路 热继电器 今天继续小编的工作经验的分享&#xff0c;今天就说说遇到的问题吧&#xff0c;今天组立熔接机出现故障&#xff0c;后面部分出现了“咕噜噜”的杂声&#xff0c;走到后面一听是电机发出的声音。没有办法了就开始拆…

Py之transformers_stream_generator:transformers_stream_generator的简介、安装、使用方法之详细攻略

Py之transformers_stream_generator&#xff1a;transformers_stream_generator的简介、安装、使用方法之详细攻略 目录 transformers_stream_generator的简介 1、Web Demo T1、original T2、stream transformers_stream_generator的安装 transformers_stream_generator的…

【Linux虚拟机】 JDK、Tomcat、MySQL安装配置讲解

目录 一、上传安装包到服务器 二、JDK与Tomcat安装 2.1 解压安装包 2.2 配置JDK环境变量 2.3 配置Tomcat环境 三、MySQL安装配置 3.1 删除默认数据库 3.2 安装mysql安装包 3.3 mysql初始化操作 四、后端接口部署 4.1 导入项目.war 4.2 新建数据库 4.3 运行服务器项目…

白票某度自媒体混剪剪辑视频素材/爬虫软件说明文档

大家好&#xff0c;我是淘小白~ 软件&#xff1a;某度自媒体混剪素材爬虫软件 语言&#xff1a;Python 说明文档&#xff1a; 1、自定义关键词采集 2、采集百度aigc视频素材&#xff0c;经过测试&#xff0c;使用剪映的文字成片某度视频素材&#xff0c;可过头条的原创检测…

SPSS单样本t检验

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

OSFP基础实验

目录 题目&#xff1a;拓扑如下 实验步骤&#xff1a; 第一步&#xff1a;设计思路 第二步&#xff1a;搭建拓扑 第三步&#xff1a;配置命令 1&#xff09;IP地址配置 2&#xff09;OSPF配置 3&#xff09;R3部分接口做静默接口 4&#xff09;缺省路由 5&#xff09…

数据结构之“初窥门径”

目录 前言&#xff1a; 一&#xff0c;数据结构起源 二&#xff0c;基本概念和术语 2.1数据 2.2数据元素 2.3数据项 2.4数据对象 2.5数据结构 三&#xff0c;逻辑结构与物理结构 3.1逻辑结构 3.1.1集合结构 3.1.2线性结构 3.1.3树形结构 3.1.4图形结构 3.2物理结…

unity中meta文件GUID异常问题

错误信息&#xff1a; The .meta file Assets/Scripts/Editor/ConvertConfigToBinary/TxtConverter.cs.meta does not have a valid GUID and its corresponding Asset file will be ignored. If this file is not malformed, please add a GUID, or delete the .meta file and…

深度了解msvcr110.dll丢失的5个解决方法以及原因

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcr110.dll丢失”。这个错误提示通常出现在运行某些程序时&#xff0c;它意味着计算机无法找到所需的动态链接库文件。本文将详细介绍msvcr110.dll丢失的原因以及5个解决方法。 一、msvc…