数据结构--顺序表

目录

1.顺序表的定义

2.顺序表的初始化

3.顺序表的扩容

4.顺序表的尾插

5.顺序表的头插

6.顺序表的尾删

7.顺序表的头删

8.顺序表的最后处理

9.顺序表指定位置进行插入 

10.顺序表指定位置进行删除


1.顺序表的定义

定义了一个结构体,用typedef定义int类型,方便以后修改类型
typedef int SLDateTyPe;

typedef struct SeqList
{
	SLDateTyPe* a;  //指向动态数组的指针

	int size;  //实际有多少人

	int capacity; //容量大小
}SL;

2.顺序表的初始化

size和capacity直接赋值为0,指针赋为空指针

void SeqListInit(SL*ps)   //修改的是结构体里面的值,用指针
{
	ps->size = 0;
	ps->capacity = 0;

	ps->a = NULL;   //a是个指针要赋为空

}

3.顺序表的扩容

这里注意扩容的情况,开始都为0的情况和空间慢了的情况


void SeqListCheck(SL* ps)
{
	//检查容量空间,满了扩容
	// 
	//一般有2种情况,一种是开始里面都没有值,都为0,第二种是
	//容量空间满了,size往后++就会越界,这时候需要扩容

	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//这里用到三目操作符,如果开始是0,给4个空间,如果不是,扩容
		//是之前的二倍,newcapacity是新空间的容量

		SLDateTyPe* tmp = (SLDateTyPe*)realloc(ps->a, newcapacity * sizeof(SLDateTyPe));
		//realloc函数的使用要熟悉,sizeof后面的是类型的大小,乘以个数,是总字节
		if (tmp == NULL)
		{
			//判断一下是否开辟失败
			printf("realloc fail\n");
			exit(-1);    //结束程序
		}

		ps->a = tmp;   //把扩容开辟的新空间赋给原来的动态数组
		ps->capacity = newcapacity;

	}

}

4.顺序表的尾插

把size当作下标看待,这里还要注意扩容的问题

数据结构--顺序表_第1张图片

void SeqListPushBack(SL* ps, SLDateTyPe x)  //尾插
{

	SeqListCheck(ps);
	
	ps->a[ps->size] = x; 
	//看图容易理解
	
	ps->size++;

}

5.顺序表的头插

数据结构--顺序表_第2张图片

void SeqListFront(SL* ps, SLDateTyPe x)  //头插
{
	//检查容量空间满了扩容
	SeqListCheck(ps);

	int end = ps->size - 1;
	//size是最后一个数据的下一个位置下标
	
	while (end >= 0)
	{
		ps->a[end] = ps->a[end + 1]; 
		end--;
	}

	ps->a[0] = x;
	ps->size++;
}

6.顺序表的尾删

顺序表尾删简单,直接让size--就可以实现了。我们打印的数据就是size范围内的数据,size减了过后就没有这个数据了。

void SeqListPopBack(SL* ps)             //尾删
{
	//这里首先保证里面是有数据的,要不然会越界
	if (ps->size == 0)
	{
		printf("SeqListPopBack is empty");
		return;
	}

	//暴力检查
	//assert(ps->size>0);
    
	ps->size--;
}

7.顺序表的头删

从前往后挪动,先挪动前面的数据再挪动后面的数据

数据结构--顺序表_第3张图片

void SeqListPopFront(SL* ps)       //头删
{
	assert(ps->size > 0);
	int begin = 1;
	while (begin < ps->size)
	{
		ps->a[begin-1] = ps->a[begin ];
		begin++;
	}
	ps->size--;

}

8.顺序表的最后处理

把ps(free掉),为空指针,size,capacity为0

void SeqListDestory(SeqList* ps)
{
	free(ps->arr);
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

我们想一个问题,如果是在面试中,给了我们很短分钟来实现顺序表,那我们应该怎么做呢

现在有另外2个函数,我们就可以复用这2个函数对顺序表的头插、尾插,就可以直接复用,大大节约了时间。

9.顺序表指定位置进行插入 

(插入的话从后往前挪动)

(假如在pos=2的位置插入,3-9依次往后挪动一个,先挪动9,按顺序挪动)

数据结构--顺序表_第4张图片

void SeqListInsert(SL* ps, int pos, SLDateTyPe x)       
{
	assert(ps);
	assert(pos>=0 && pos<=ps->size);   //pos不能越界   
	//实现尾插的时候要pos要=size,相当于在尾部直接插入

	SeqListCheck(ps);
	//检查一下容量的问题,扩容
	
	int end = ps->size - 1;

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

}

10.顺序表指定位置进行删除

数据结构--顺序表_第5张图片

void SeqListErase(SL* ps, int pos)       
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size-1);

	int begin = pos;
	while (begin < ps->size-1)  
	//删除的时候注意下标,pos的取值范围size-1已经是最大的了,begin+1会造成越界
	//这里用ps->size-1代替
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}
void SeqlistErase(Sq* ps, int pos)
{
	assert(ps);

	assert(pos >= 0 && pos size);

	int begin = pos+1;

	while (begin < ps->size )
	{
		ps->a[begin-1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

利用这两个函数可以很快的把前面的东西写出来,很方便。

尾插:尾插其实就是对顺序表最后的位置插入元素

SeqListInsert(ps, ps->size,x);


头插:头插就是对0的位置插入元素

SeqListInsert(ps,0,x);


尾删:尾删也是和尾插一样的,对最后的位置删除

SeqListErase(ps, ps->size-1);


头删:头删是对0的位置开始删除

SeqListErase(ps, 0);

11.顺序表打印

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

}

12.顺序表查找

int  SeqListFind(SL* ps, SLDateTyPe x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if(ps->a[i] == x);
		return i;//返回的是下标
	}
	return -1;
}

13.顺序表修改

int SeqListModifyt(SL* ps, int pos, SLDateTyPe x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	ps->a[pos] = x;

}

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