【数据结构】顺序表

顺序表

顺序表是线性表的一种。
线性表:具有相同特性的数据结构,线性表在逻辑结构上一定是连续的,在物理结构上不一定是连续的。
顺序表:用顺序存储的方式实现线性表,把逻辑上相邻的两个变量在物理位置也相邻的存储。

顺序表的底层是数组
(文章结尾处放完整代码)
顺序表分类:

  • 静态顺序表:底层是一个静态数组。静态顺序表并不方便,当数组的空间给大时,会造成空间浪费;当数组的空间给小了,会造成数据的丢失。

  • 动态顺序表:一个指针,动态开辟内层。可以动态的增容。

创建一个顺序表:
(静态顺序表顺序表)

typedef struct SeqList
{
	int arr[100];
	int size;//记录的是顺序表有效数据个数
	int capacity;//记录的是有效空间大小
}

静态顺序表这里不过多阐述,主要动态顺序表。

typedef int SLDatatype;//为什么要对Int重命名?
typedef struct SeqList
{
	SLDatatype* arr;
	SLDatatype size;//记录的是顺序表有效数据个数
	SLDatatype capacity;//记录的是有效空间大小
}

为什么要对int重命名?如果我们后面需求变更,要在顺序表中存储的数据类型是char类型,只需要修改typedef int SLDatatype;即可。

顺序表初始化

void SeqListInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

为什么要对顺序表初始化?我们知道,顺序表的空间是我们动态内层分配的来的,在将这块空间分配给顺序表前,这块空间中可能已经存储了其他值(脏数据),那么,我们在使用顺序表的时候可能会得到一些不是我们想要的值。

顺序表的销毁

//顺序表的销毁
void SeqListDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->capacity = ps->size = 0;
}

在使用完顺序表后,要将空间归还,否则会造成内存泄漏。如果不归还,可能在当下不会有什么问题,但时间久了,被占用的空间多了,程序就会出现问题。

顺序表的头/尾插


void SLCheckCapacity(SL* ps)//检查顺序表的空间是否足够
{
	if (ps->capacity == ps->size)//如果空间不足,则增容。当有效数据个数与顺便的空间大小相等时,表示空间以用完。
	{
		int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
		SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype));
		if (tmp == NULL)
		{
			perror("realloc Fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

void SeqPushBack(SL*ps,SLDatatype x)//尾插
{
	assert(ps);//传入的数值不能为NULL,因为不能对空指针解引用
	SLCheckCapacity(ps);//检查顺序表空间是否足够
	ps->arr[ps->size++] = x;
}
void SeqPushFront(SL*ps,SLDatatype x)//头插
{
	assert(ps);
	SLCheckCapacity(ps);//检查顺序表空间是否足够

	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

顺序表的头/尾删

void SeqPopBcack(SL*ps)//尾删
{
	assert(ps);
	assert(ps->size);
	//ps->arr[ps->size - 1] = 0;  可要可不要
	ps->size--;//当作数组来理解,就是把数组的长度减1
}

void SeqPopFront(SL*ps)//头删
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//当作数组来理解,头删就是将所有数据前移一位,第一个数据直接被后面的数据覆盖掉。
	}
	ps->size--;
}

顺序表插入数据

void SLInsert(SL*ps,SLDatatype x,int pos)//在指定位置之前插入数据
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)//当作数组来理解,就是从pos下标处开始,(包括pos下标处),每个元素后移一位,再在pos处插入数据
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;//在Pos位置插入数据
	ps->size++;
}
void SLErase(SL *ps,int pos)//删除指定位置的数据
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for(int i=pos;i<ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];//当作数组,就是从pos下标开始(不包括pos下标位置),每个元素前移一位,把Pos位置处的数据覆盖掉
	}
	ps->size--;
}

顺序表查找数据

int SLFind(SL *ps,SLDatatype x )//查找数据
{
	assert(ps);
	for (int i=0;i<ps->size;i++)
	{
		if (ps->arr[i]==x)
		{
			return i;
		}
	}
	return -1;
}

顺序表完整代码

将顺序表的代码分别放在两个个文件下,一个.h头文件,一个.c文件,最好在创建一个test.c文件对顺序表代码进行测试就行了。
SeqList.h文件 头文件

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


typedef int SLDatatype;

//顺序表
typedef struct SeqList
{
	SLDatatype* arr;
	SLDatatype size;//元素个数
	SLDatatype capacity;//空间大小
}SL;

void SeqPrint(SL ps);//打印

void SeqListInit(SL*ps);//顺序表初始化

void SeqListDestory(SL*ps);//顺序表的销毁

void SeqPushBack(SL*ps,SLDatatype x);//尾插
void SeqPushFront(SL*ps,SLDatatype x);//头插

void SeqPopBcack(SL*ps);//尾删
void SeqPopFront(SL*ps);//头删

void SLInsert(SL*ps,SLDatatype x,int pos);//在指定位置之前插入数据
void SLErase(SL *ps,int pos);//删除指定位置的数据

int SLFind(SL *ps,SLDatatype x );//查找数据

SeqList.c文件,放的是顺序表函数的实现

#include"SeqList.h"

void SeqPrint(SL ps)
{
	for (int i=0;i<ps.size;i++)
	{
		printf("%d ", ps.arr[i]);
	}
	printf("\n");
}

//顺序表的初始化
void SeqListInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}


//顺序表的销毁
void SeqListDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->capacity = ps->size = 0;
}

void SLCheckCapacity(SL* ps)
{
	
	if (ps->capacity == ps->size)
	{
		int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
		SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype));
		if (tmp == NULL)
		{
			perror("realloc Fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

//尾插
void SeqPushBack(SL* ps, SLDatatype x)
{
	assert(ps);
	SLCheckCapacity(ps);
	ps->arr[ps->size++] = x;
}

//头插
void SeqPushFront(SL* ps, SLDatatype x)
{
	assert(ps);
	SLCheckCapacity(ps);

	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;

}

void SeqPopBcack(SL* ps)//尾删
{
	assert(ps);
	assert(ps->size);
	//ps->arr[ps->size - 1] = 0;  可要可不要
	ps->size--;

}


void SeqPopFront(SL* ps)//头删
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

void SLInsert(SL* ps, SLDatatype x, int pos)//在指定位置之前插入数据
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}
void SLErase(SL* ps, int pos)//删除指定位置的数据
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for(int i=pos;i<ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

int SLFind(SL* ps, SLDatatype x)//查找数据
{
	assert(ps);
	for (int i=0;i<ps->size;i++)
	{
		if (ps->arr[i]==x)
		{
			return i;
		}
	}
	return -1;
}

test.c测试文件,这个文件可以不用看了,但是为了文章的完整性,所有我写在了这里。

#include"SeqList.h"

void test1()
{
	SL s;
	SeqListInit(&s);
	/*
	SeqPushBack(&s,1);
	SeqPushBack(&s,2);
	SeqPushBack(&s,3);
	SeqPushBack(&s,4);
	SeqPrint(s);*/

	SeqPushFront(&s,1);
	SeqPushFront(&s,2);
	SeqPushFront(&s,3);
	SeqPrint(s); 
	//SeqPopBcack(&s);
	//SeqPrint(s);

	//SeqPopBcack(&s);
	//SeqPrint(s);

	//SeqPopBcack(&s);
	//SeqPrint(s);

	//SeqPopBcack(&s);
	//SeqPrint(s);

	/*1111*/

	/*SeqPopFront(&s);
	SeqPrint(s);*/


	/*SLInsert(&s,9,s.size);
	SeqPrint(s);
	SLErase(&s,s.size-1);
	SeqPrint(s);*/

	int find=SLFind(&s,2);
	if (find==-1)
	{
		printf("没找到");
	}
	else
	{
		printf("找到了");
	}

	SeqListDestory(&s);
}

int main()
{
	test1();
	return 0;
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
顺序是一种常见的数据结构,用于存储一组具有相同类型的元素。它的基本操作包括创建、查找、插入和删除等。 在C语言中,可以通过使用数组来实现顺序。我们可以定义一个数组来存储顺序的元素,然后通过索引来访问和操作其中的元素。引用中的代码展示了一个简单的顺序的例子,它使用了C语言来实现。在这个例子中,我们可以看到如何创建一个顺序、插入元素、删除元素以及查找元素的前驱和后继。 引用中的代码是一个测试顺序基本操作的例子。它使用了一个自定义的List类来实现顺序,并对其进行了各种操作,包括插入元素、删除元素、查找元素的前驱和后继以及遍历整个顺序顺序的结构体定义可以根据具体的需求进行定义。在引用中的代码中,定义了一个结构体ConnTimeout,其中包含了一个int类型的fd和一个time_t类型的timeout成员变量。这个结构体可以用来示连接超时的信息。 总而言之,顺序是一种常见的数据结构,可以通过使用数组来实现。在C语言中,可以使用数组和相关的操作来创建、查找、插入和删除顺序中的元素。结构体的定义可以根据具体的需求进行自定义。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [数据结构顺序c++代码](https://download.csdn.net/download/qq_46546083/13458006)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++数据结构顺序(模板类实现)](https://blog.csdn.net/sagjhdj/article/details/123260460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【数据结构顺序(C++)](https://blog.csdn.net/qq_51604330/article/details/120600041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值