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

个人主页
⭐个人专栏——数据结构学习⭐
点击关注一起学习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. 在缩小存储空间时,可能会浪费部分内存空间

【数据结构】顺序表实例探究_第1张图片

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++;
}

【数据结构】顺序表实例探究_第2张图片

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;
}

【数据结构】顺序表实例探究_第3张图片

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++;
}

【数据结构】顺序表实例探究_第4张图片

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;
}

【数据结构】顺序表实例探究_第5张图片

4.8 顺序表尾删

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

SeqList.h声明函数

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

SeqList.c定义函数

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

【数据结构】顺序表实例探究_第6张图片

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;
}

【数据结构】顺序表实例探究_第7张图片

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--;
}

【数据结构】顺序表实例探究_第8张图片

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;
}

【数据结构】顺序表实例探究_第9张图片

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++;
}

【数据结构】顺序表实例探究_第10张图片

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;
}

【数据结构】顺序表实例探究_第11张图片

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--;

}

【数据结构】顺序表实例探究_第12张图片

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;
}

【数据结构】顺序表实例探究_第13张图片

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;
}

【数据结构】顺序表实例探究_第14张图片

5. 所有代码整理

5.1 SeqList.h头文件

#pragma once
#include 
#include 
#include 

//把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--];
//	}
//}


你可能感兴趣的:(数据结构学习,数据结构,c语言,链表)