【数据结构】顺序表

avatar
作者
筋斗云
阅读量:1

顺序表

顺序表

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

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

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

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

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

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

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!