顺序表的简单原理实现

注意看看代码的注释!!!!!(干货)

主要是功能是增删改查这些;

源码:头文件中

#define  _CRT_SECURE_NO_WARNINGS 1
#include 
#include 
#include 
typedef int SLDatatype;
int newcapacity = 0;
struct SeqList
{
	SLDatatype* data;//其实我们有了地址还可以搞链表,我们动态顺序表存储方式其实是顺序存储的,所以我们不需要去记节点
	int size;
	int capacity;
};
typedef struct SeqList SL;
void SLInti(SL* ps);//初始化,千万不要写成void SLInti(SL s),因为函数在传参的时候,形参是实参的一份临时拷贝
void SLInti(SL* ps)//一定得开辟个空间变量,因为他不像链表一样有个地址即可
{
	ps->data = NULL;
	ps->capacity = 0;
	ps->size = 0;
}
void CheckCapacity(SL* ps);//检查容量
void CheckCapacity(SL* ps)
{
	if (newcapacity == ps->capacity)
	{
		newcapacity = ps->capacity == 0 ? 4 : newcapacity * 2;//这个有什么作用呢,
	   //因为这里是我们如果空间为0,扩两倍那等于没阔,所以我们如果是0的话空间就给4,而且用三目操作符又比
	   //ifelse代码更简介,效率更高
		SLDatatype* ptr = (SLDatatype*)realloc(ps->data, newcapacity * sizeof(SLDatatype));
		if (ptr == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->data = ptr;//为什么要给指针赋值,因为当我们在申请空间时,操作系统会去识别你需要的的空间是否被占用,如果
		//被占用那么操作系统会去重新分配个地址,释放原来的空间,并把原先的数据拷贝到新地址指向的空间
		//,因为我SL * ps们不知道realloc扩容后返回的地址是异地扩容还是原地扩容
	}
}
void SListPushBack(SL* ps, SLDatatype X);//尾插
void SListPushBack(SL* ps, SLDatatype X)//尾插
{
	CheckCapacity(ps);
	ps->data[ps->size] = X;
	++ps->capacity;
	++ps->size;
}
void SListPushFont(SL* ps, SLDatatype X);//头插
void SListPushFont(SL* ps, SLDatatype X)//头插
{
	assert(ps->size >= 0);//只能在有效数据内插入
	CheckCapacity(ps);
	int i = 0;
	for (i=ps->size;i>=1;--i)//从最后一个数据开始依次往后覆盖,最后把首元素插入
	{
		assert(ps->size < newcapacity);
		ps->data[i] = ps->data[i - 1];
	}
	ps->data[0] = X;//首元素插入
	++ps->size;
	++ps->capacity;
}
void SListPopBack(SL* ps, SLDatatype X);//尾删
void SListPopBack(SL* ps,SLDatatype X)
{	
	assert(ps->size > 0);
	--ps->size;//删除一个size减去一个
}
void SListPrint(SL* ps);//打印数据
void SListPrint(SL* ps)
{
	for (int i=0;i<=ps->size-1;i++)
	{
		printf("%d->", ps->data[i]);//我们只打印有效数据就行,因为我们的size和capacity
	}//一直在追踪整个顺序表,我添加一个size+1一次,capacity+1次
	printf("\n");
}
void SListPopFront(SL* ps);//头删
void SListPopFront(SL* ps)
{
	assert(ps->size > 0);//判断里面有木有数
	assert(ps->capacity > 0);//没有就不删除
	for (int i=1;isize;i++)//直接看作删完,后面覆盖到前面,从第二个开始依次往前覆盖
	{
		ps->data[i - 1] = ps->data[i];
	}
	--ps->size;//删完之后减去个数
	--ps->capacity;//删完之后减去占用空间
}
int SListSearch(SL* ps, SLDatatype X);//搜索你要的数——返回下标,没找到返回-1
int SListSearch(SL* ps, SLDatatype X)//这里的SLDatatype X是你要找的数
{
	assert(ps->capacity > 0);
	for (int i=0;isize;i++)
	{
		if (ps->data[i]==X)
		{
			return i;//找到想要的数,返回他的下标
		}
	}
	return -1;//没找到返回-1
}
void SListDesignInsert(SL* ps, SLDatatype X,int x);//指定插入——找到那个数我们才插入,否则就不插入,
//所以我们在这里会判断一个是否找到下标
void SListDesignInsert(SL* ps, SLDatatype X,int x)//这里的SLDatatype X是我们找到的下标
{
	assert(ps->capacity > 0);

	CheckCapacity(ps);
	for (int i=ps->size;i>X;i--)//从后面的数依次存到后面
	{
		ps->data[i] = ps->data[i - 1];//没问题
	}
	ps->data[X] = x;
	++ps->size;
	++ps->capacity;
}
void SListDesignErase(SL* ps, SLDatatype X);
void SListDesignErase(SL* ps, SLDatatype X)//指定删除
{
	assert(ps->capacity > 0);
	for (int i=0;isize;i++)
	{
		if (X == ps->data[i])
		{
			int j = 0;
			for (j = i;j < ps->size-1;j++)//从前面的顺序依次往前面放
			{
				ps->data[j] = ps->data[j+1];//没问题
			}
			--ps->size;
			--ps->capacity;
			break;
		}
	}
}
void SListInsert(SL* ps, SLDatatype X,int x);
void SListInsert(SL* ps,SLDatatype X,int x)//随机插入---(其实我们也可以变成头插)——此时的SLDatatype X是下标
{
	assert(ps);
	assert(X >= 0 && X<=ps->size);
	CheckCapacity(ps);
	int Src = X ;
	int End = ps->size;
	while (Srcdata[End] = ps->data[End - 1];
		--End;
	}
	ps->data[X] = x;
	++ps->size;
	++ps->capacity;
}
void SListErase(SL* ps, SLDatatype X);//随机删除——此时的SLDatatype X是下标
void SListErase(SL* ps, SLDatatype X)
{
	assert(ps);
	assert(ps->size>0);
	assert(X >= 0 && X<=ps->size - 1);
	int Src = X;
	int End = ps->size - 1;
	while (Srcdata[Src] = ps->data[Src + 1];
		Src++;
	}
	--ps->size;
	--ps->capacity;
}
void Dsetory(SL* ps);
void Dsetory(SL* ps)
{
	free(ps->data);
	ps->data = NULL;
	ps->capacity = 0;
	newcapacity = 0;
	ps->size = 0;
}

源码:源文件中

#define  _CRT_SECURE_NO_WARNINGS 1
#include "10.26.h"
#include 
int main()
{
	SL s1;
	SLInti(&s1);
	SListPushFont(&s1, 2);
	SListPushFont(&s1, 3);
	SListPushFont(&s1, 4);
	SListPushFont(&s1, 5);
	SListPushFont(&s1, 6);
	SListDesignInsert(&s1, SListSearch(&s1, 6),7);
	SListPushBack(&s1, 7);
	SListPushBack(&s1, 8);
	SListPushBack(&s1, 9);
	SListPushBack(&s1, 10);
	SListDesignInsert(&s1, SListSearch(&s1, 4), 7);
	SListDesignInsert(&s1, SListSearch(&s1, 6), 7);
	SListDesignErase(&s1, SListSearch(&s1, 6), 7);
	SListPrint(&s1);
	SListInsert(&s1, 2, 8);
	SListInsert(&s1, 0, 8);
	SListInsert(&s1, 13, 8);
	SListPrint(&s1);
	SListErase(&s1, 0);
	SListErase(&s1, 10);
	SListErase(&s1, 2);
	SListPrint(&s1);
	Dsetory(&s1);
}

分析1

 这个有些基础弱的可能会被他搞混,其实我们的原理是这样的

顺序表的简单原理实现_第1张图片

 并且我们的结构体内容也不会随着开辟SLDatatype*指向的空间而改变

顺序表的简单原理实现_第2张图片

 并且里面有很多需要注意的点

1.

2. 

顺序表的简单原理实现_第3张图片

3.

顺序表的简单原理实现_第4张图片

4.

顺序表的简单原理实现_第5张图片

5. 

顺序表的简单原理实现_第6张图片

 6.

每次记得断言一下,然后继续优化,继续测试慢慢完善

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