顺序表的基本概念和代码实现(C语言)

目录

一、顺序表的基本概念

二、顺序表的定义和基本算法

动态顺序表

基本算法

⭕整体前移

⭕整体后移

⭕遍历查找 

 三、顺序表的接口函数和实现

⭕初始化顺序表:malloc出3个字节的空间

 ⭕增容检查:每次插入数据都要检查是否sz和capacity相等,若相等就追加2个字节的空间

  ⭕打印顺序表数据

 ⭕头插:在sl->data[0]处插入数据,需要数据整体后移

 ⭕头删:删除sl->data[0]处的数据,需要数据整体前移

 ⭕尾插:在sl->data[sl->sz]处插入数据

 ⭕尾删:删除sl->data[sl->sz]处的数据

 ⭕在指定位置插入数据

 ⭕删除指定位置的数据

 ⭕顺序表的销毁

 四、总结

SeqList.c

SeqList.h


一、顺序表的基本概念

①线性表:线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

②顺序表:由物理地址连续的存储单元构成,一般情况下采用数组存储。顺序表是线性表的一种。


基本算法:整体前移、后移和遍历查找。

增:包括头插、尾插和指定位置插入数据,其中头插和指定位置插入数据运用整体后移

删:包括头删、尾删和删除指定位置数据,其中头删和删除指定位置数据运用整体前移

查:运用遍历查找

改:运用遍历查找

二、顺序表的定义和基本算法

动态顺序表

由于顺序表中存储的数据是相同类型的,所以我们将其类型定义为SLDataType,这样方便修改顺序表数据类型。

顺序表的基本概念和代码实现(C语言)_第1张图片

data定义成指针,用C语言中的动态开辟函数在堆区开辟一块空间,data中保存这些空间的第一块空间的地址;

capacity表示这块空间的总容量;

sz表示已存储数据的个数。

基本算法


整体前移

 ​​​顺序表的基本概念和代码实现(C语言)_第2张图片

for (i = pos; i < right - 1; i++)
{
	sl->data[i] = sl->data[i + 1];
}

整体后移

 顺序表的基本概念和代码实现(C语言)_第3张图片

for (i = right; i >= pos; i--)
{
	sl->data[i+1] = sl->data[i];
}

遍历查找 

for(i=0;i<=right;i++)
{
    if(sl->data[i]==x)
    {
        return i;
    }
}

 三、顺序表的接口函数和实现

初始化顺序表:malloc出3个字节的空间

#define Default_sz 3
void InitSL(SList* sl)
{
	assert(sl);
	sl->data = (SList*)malloc(Default_sz * sizeof(SList));
	sl->capacity = Default_sz;
	sl->sz = 0;
}

 ⭕增容检查:每次插入数据都要检查是否sz和capacity相等,若相等就追加2个字节的空间

int check_capacity(SList* sl)
{
	if (sl->capacity == sl->sz)
	{
		SList* tmp = (SList*)realloc(sl->data, (sl->capacity + 2) * sizeof(SList));
		if (tmp == NULL)
		{
			perror("realloc");
			return 0;//增容失败
		}
		else
		{
			sl->data = tmp;
			sl->capacity += 2;
			return 1;
		}
	}
	return 1;
}

  ⭕打印顺序表数据

void SL_print(const SList* sl)
{
	int i = 0;
	for (i = 0; i < sl->sz; i++)
	{
		printf("%d ", sl->data[i]);
	}
}

 ⭕头插:在sl->data[0]处插入数据,需要数据整体后移

void SL_pushfront(SList* sl,SLDataType x)
{
	assert(sl);
	if (0 == check_capacity(sl))
	{
		printf("顺序表容量已满\n");
		return;
	}
	int i = 0;
    //整体后移
	for (i = sl->sz; i >= 0; i--)
	{
		sl->data[i+1] = sl->data[i];
	}
	sl->data[0] = x;
	sl->sz++;
}

 ⭕头删:删除sl->data[0]处的数据,需要数据整体前移

void SL_popfront(SList* sl)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	int i = 0;
	//整体前移
	for (i = 0; i < sl->sz - 1; i++)
	{
		sl->data[i] = sl->data[i + 1];
	}
	sl->sz--;
}

 ⭕尾插:在sl->data[sl->sz]处插入数据


void SL_pushback(SList* sl,SLDataType x)
{
	if (0 == check_capacity(sl))
	{
		printf("容量满\n");
		return;
	}
	sl->data[sl->sz] = x;
	sl->sz++;
}

 ⭕尾删:删除sl->data[sl->sz]处的数据

void SL_popback(SList* sl)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	sl->sz--;
}

 ⭕查找

int SL_search(SList* sl, SLDataType x)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return 0;
	}
	int i = 0;
	for (i = 0; i < sl->sz; i++)
	{
		if (sl->data[i] == x)
		{
			return i;
		}
	}
	return 0;//找不到
}

 ⭕在指定位置插入数据

void SL_insert(SList* sl, SLDataType x, SLDataType pos)
{
	assert(pos >=0 && pos<=sl->sz);
	if (0 == check_capacity(sl))
	{
		printf("顺序表容量已满\n");
		return;
	}
	int i = 0;
	//sl->data[pos]到sl->data[sl->sz]的数据整体后移
	for (i = sl->sz; i >= pos; i--)
	{
		sl->data[i + 1] = sl->data[i];
	}
	sl->data[pos] = x;
	sl->sz++;
}

 ⭕删除指定位置的数据

void SL_erase(SList* sl, SLDataType pos)
{
	assert(pos >=0 && pos<=sl->sz);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	int i = 0;
	for (i = pos; i < sl->sz-1; i++)
	{
		sl->data[i] = sl->data[i + 1];
	}
	sl->sz--;
}

 ⭕顺序表的销毁

void SL_destroy(SList* sl)
{
	sl->capacity = sl->sz = 0;
	free(sl->data);
	sl->data = NULL;
}

  ⭕修改任意位置的数据

void SL_change(SList* sl, SLDataType x,int pos)
{
	assert(sl);
	sl->data[pos] = x;
}


 四、总结

改:时间复杂度为O(1)

由于顺序表使用数组实现的,所以顺序表访问效率高,访问任意下标的数据时间复杂度为O(1)

增:时间复杂度为O(n)

删:时间复杂度为O(n)

查:时间复杂度为O(n)

顺序表的查找、插入和删除的效率相对低,时间复杂度都是O(n) ,其中尾插和尾删是最好的情况,时间复杂度为O(1)

 顺序表的代码全部整理在这里了:

SeqList.c

#include"SeqList.h"
//初始化顺序表
void InitSL(SList* sl)
{
	assert(sl);
	sl->data = (SList*)malloc(Default_sz * sizeof(SList));
	sl->capacity = Default_sz;
	sl->sz = 0;
}
//增容检查
int check_capacity(SList* sl)
{
	if (sl->capacity == sl->sz)
	{
		SList* tmp = (SList*)realloc(sl->data, (sl->capacity + 2) * sizeof(SList));
		if (tmp == NULL)
		{
			perror("realloc");
			return 0;
		}
		else
		{
			sl->data = tmp;
			sl->capacity += 2;
			return 1;
		}
	}
	return 1;
}
//尾插
void SL_pushback(SList* sl,SLDataType x)
{
	if (0 == check_capacity(sl))
	{
		printf("容量满\n");
		return;
	}
	sl->data[sl->sz] = x;
	sl->sz++;
}
//尾删
void SL_popback(SList* sl)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	sl->sz--;
}
//头删
void SL_popfront(SList* sl)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	int i = 0;
	//整体前移
	for (i = 0; i < sl->sz - 1; i++)
	{
		sl->data[i] = sl->data[i + 1];
	}
	sl->sz--;
}
//头插
void SL_pushfront(SList* sl,SLDataType x)
{
	assert(sl);
	if (0 == check_capacity(sl))
	{
		printf("顺序表容量已满\n");
		return;
	}
	int i = 0;
    //整体后移
	for (i = sl->sz; i >= 0; i--)
	{
		sl->data[i+1] = sl->data[i];
	}
	sl->data[0] = x;
	sl->sz++;
}
//查找
int SL_search(SList* sl, SLDataType x)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return 0;
	}
	int i = 0;
	for (i = 0; i < sl->sz; i++)
	{
		if (sl->data[i] == x)
		{
			return i;
		}
	}
	return 0;//找不到
}
//指定位置插入数据
void SL_insert(SList* sl, SLDataType x, int pos)
{
	assert(pos >=0 && pos<=sl->sz);
	if (0 == check_capacity(sl))
	{
		printf("顺序表容量已满\n");
		return;
	}
	int i = 0;
	//sl->data[pos]到sl->data[sl->sz]的数据整体后移
	for (i = sl->sz; i >= pos; i--)
	{
		sl->data[i + 1] = sl->data[i];
	}
	sl->data[pos] = x;
	sl->sz++;
}
//指定位置删除数据
void SL_erase(SList* sl, int pos)
{
	assert(pos >=0 && pos<=sl->sz);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	int i = 0;
	for (i = pos; i < sl->sz-1; i++)
	{
		sl->data[i] = sl->data[i + 1];
	}
	sl->sz--;
}
//修改指定位置的数据
void SL_change(SList* sl, SLDataType x,int pos)
{
	assert(sl);
	if (sl->sz == 0)
	{
		printf("顺序表无数据\n");
		return;
	}
	sl->data[pos] = x;
}
//打印信息
void SL_print(const SList* sl)
{
	int i = 0;
	for (i = 0; i < sl->sz; i++)
	{
		printf("%d ", sl->data[i]);
	}
}
//销毁顺序表
void SL_destroy(SList* sl)
{
	sl->capacity = sl->sz = 0;
	free(sl->data);
	sl->data = NULL;
}

SeqList.h

#pragma once 
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include

#define Default_sz 3

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* data;
	int capacity; 
	int sz;
}SList;

//初始化
void InitSL(SList* sl);
//打印
void SL_print(const SList* sl);
//尾插
void SL_pushback(SList* sl,SLDataType x);
//尾删
void SL_popback(SList* sl);
//头插
void SL_pushfront(SList* sl,SLDataType x);
//头删
void SL_popfront(SList* sl);
//查找
int SL_search(SList* sl, SLDataType x);
//指定位置插入数据
void SL_insert(SList* sl, SLDataType x, int pos);
//指定位置删除数据
void SL_erase(SList* sl, int pos);
//修改指定位置的数据
void SL_change(SList* sl, SLDataType x, int pos);
//销毁顺序表
void SL_destroy(SList* sl);

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