初阶数据结构-顺序表

顺序表

  • 顺序表的概念
  • 接口实现
    • 顺序表基本功能
    • 静态顺序表的创建
    • 动态顺序表的创建
    • 顺序表的初始化
    • 顺序表的销毁
    • 顺序表的打印
    • 顺序表的检查容量函数
    • 顺序表的尾插
    • 顺序表的头插
    • 顺序表的尾删
    • 顺序表的头删
    • 顺序表的中间插入
    • 顺序表的中间删除
    • 顺序表的查找
    • 顺序表的修改
  • 顺序表的测试主函数

顺序表的概念

  顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组
上完成数据的增删查改。
  顺序表一般可以分为:1. 静态顺序表:使用定长数组存储元素。2. 动态顺序表:使用动态开辟的数组存储。
初阶数据结构-顺序表_第1张图片

接口实现

  静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

顺序表基本功能

//初始化
void SLInit(SL *ps1);

//销毁
void SLDestroy(SL *ps1);
//打印
void SLPrint(SL* ps1);

//STL命名风格
//尾插
void SLPushBack(SL* ps1, SLDatatype x);
//头插
void SLPushFront(SL* ps1, SLDatatype x);
//尾删
void SLPopBack(SL* ps1);
//头删
void SLPopFront(SL* ps1);

//中间插入
void SLInsert(SL* ps1, int pos, SLDatatype x);
//中间删除
void SLErase(SL* ps1, int pos);

//查找
int SLFind(SL* ps1, SLDatatype x);

//修改
void SLModify(SL* ps1, int pos, SLDatatype x);

静态顺序表的创建

#define N 10
typedef int SLDatatype;

struct Seqlist
{
	SLDatatype a[N];
	int size;
};

动态顺序表的创建

typedef int SLDatatype; 
typedef struct SeqList
{
	SLDatatype* a;
	int size;//存储的有效数据的个数
	int capacity; //容量
}SL;

顺序表的初始化

对指针初始化为空,数据个数初始化为0,数据容量动态开辟初始化为4

void SLInit(SL* ps1)
{
	ps1->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);
	if (ps1->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps1->capacity = 4;
	ps1->size = 0;
}

顺序表的销毁

对指针置空,数据个数置0,数据容量置0

void SLDestroy(SL* ps1)
{
	free(ps1->a);
	ps1->a=NULL;
	ps1->size = 0;
	ps1->capacity = 0;
}

顺序表的打印

对顺序表的所有数据进行打印

void SLPrint(SL* ps1)
{
	for (int i = 0; i < ps1->size; i++)
	{
		printf("%d ", ps1->a[i]);
	}
	printf("\n");
}

顺序表的检查容量函数

如果数据个数等于数据容量,用realloc进行2倍扩容

void SLCheckCapacity(SL* ps1)
{
	if (ps1->size == ps1->capacity)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(ps1->a, sizeof(SLDatatype) * ps1->capacity* 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps1->a = tmp;
		ps1->capacity *= 2;
	}
}

顺序表的尾插

初阶数据结构-顺序表_第2张图片
将数据放到最后一个数据后面,再将size++

void SLPushBack(SL* ps1, SLDatatype x)
{
	//ps1->a[ps1->size] = x;
	//ps1->size++;

	/*SLCheckCapacity(ps1);
	ps1->a[ps1->size++] = x;*/
	SLInsert(ps1, ps1->size, x);
}

顺序表的头插

初阶数据结构-顺序表_第3张图片
将end从后往前挪动数据,最后将数据放到第一个位置

void SLPushFront(SL* ps1, SLDatatype x)
{
	//SLCheckCapacity(ps1);
	挪动数据
	//int end = ps1->size - 1;
	//while (end >= 0)
	//{
	//	ps1->a[end + 1] = ps1->a[end];
	//	--end;
	//}
	//ps1->a[0] = x;
	//ps1->size++;
	SLInsert(ps1, 0, x);
}

顺序表的尾删

初阶数据结构-顺序表_第4张图片
直接对size–

void SLPopBack(SL* ps1)
{
	暴力检查
	//assert(ps1->size > 0);
	温柔的检查
	if (ps1->size == 0)
	//	//return;
	ps1->a[ps1->size - 1] = 0;
	//ps1->size--;

	SLErase(ps1, ps1->size - 1);
}

顺序表的头删

初阶数据结构-顺序表_第5张图片
用后面的数据来覆盖前面的数据,直到start到size-2的位置

void SLPopFront(SL* ps1)
{
	暴力检查
	//assert(ps1->size > 0);
	///*int start = 0;
	//while (start < ps1->size-1)
	//{
	//	ps1->a[start - 1] = ps1->a[start];
	//	start++;
	//}*/

	//int start = 1;
	//while (start < ps1->size)
	//{
	//	ps1->a[start - 1] = ps1->a[start];
	//	start++;
	//}
	//ps1->size--;

	SLErase(ps1, 0);
}

顺序表的中间插入

初阶数据结构-顺序表_第6张图片
从end位置开始从前往后覆盖,最后在pos位置插入数据

void SLInsert(SL* ps1, int pos, SLDatatype x)
{
	assert(0 <=pos && pos <= ps1->size);
	SLCheckCapacity(ps1);

	int end = ps1->size - 1;
	while (end >= pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		--end;
	}
	ps1->a[pos] = x;
	ps1->size++;
}

顺序表的中间删除

初阶数据结构-顺序表_第7张图片
从start后面的一个位置开始往前覆盖数据,直到start为size-1

void SLErase(SL* ps1, int pos)
{
	assert(0 <= pos && pos < ps1->size);
	//assert(ps1->size > 0);

	int start = pos + 1;
	while (start < ps1->size)
	{
		ps1->a[start - 1] = ps1->a[start];
		++start;
	}
	ps1->size--;
}

顺序表的查找

找到返回下标,没有找到返回-1

int SLFind(SL* ps1, SLDatatype x)
{
	for (int i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

顺序表的修改

对pos位置的数据进行修改

void SLModify(SL* ps1, int pos, SLDatatype x)
{
	assert(0 <= pos && pos < ps1->size);
	ps1->a[pos] = x;
}

顺序表的测试主函数

void menu()
{
	printf("********************************\n");
	printf("*****1.尾插数据 2.尾删数据******\n");
	printf("*****3.头插数据 4.头删数据******\n");
	printf("*****5.打印数据 -1.退出*********\n");
	printf("********************************\n");
}

int main()
{
	int option = 0;
	SL s;
	SLInit(&s);
	while (option != -1)
	{
		menu();
		printf("请输入你的操作:");
		scanf("%d", &option);
		if (option == 1)
		{
			/*printf("请输入要尾插的数据,以-1结束:");
			int x = 0;
			scanf("%d", &x);
			while (x != -1)
			{
				SLPushBack(&s, x);
				scanf("%d", &x);
			}*/
			int n = 0;
			printf("请输入要尾插的数据个数,再依次输入要插入的数据:");
			scanf("%d", &n);
			int x = 0;
			while (n > 0)
			{
				scanf("%d", &x);
				SLPushBack(&s, x);
				n--;
			}
		}
		else if (option == 5)
		{
			SLPrint(&s);
		}
		else if (option == -1)
		{
			break;
		}
		else
		{
			printf("无此选项,请重新输入");
		}
	}
	SLDestroy(&s);
	//TestSeqList1();
	return 0;
}

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