数据结构学习day2——顺序表的完整实现

        今天是顺序表学习的第二天,把顺序表的增,删,改,查等大部分的操作都实现了一遍,包含了以下操作:

1. 顺序表中对应位置元素的删除

        在这一步,我们设计一个函数,参数是顺序表的起始地址和一个想要删除的位置,我们首先用断言语句assert(暴力检查的语句)来检查删除的位置是否正确(pos >= 0 && pos < s->sz),然后写一个循环,让当前元素被后一个元素覆盖即可(i要小于s->sz-1,不能小于s->是因为i会指向最后一个元素,从而导致顺序表外的一个未知元素被拷贝)

//函数功能:顺序表的中间删除
void SLerase(SeqList* s,int pos)
{
	assert(pos >= 0 && pos < s->sz && s->sz > 0);
	for(int i = pos;i < s->sz-1;i++)
	{
		s->data[i] = s->data[i+1];
	}
	s->sz--;
}

2. 顺序表的头删

        其实就是对应位置元素的删除中,把对应元素修改为零即可,可以在这个函数中直接调用元素删除的函数

//函数功能:顺序表的头删
void SLpopFront(SeqList* s)
{
	SLerase(s,0);
}

3. 顺序表的尾删

        其实就是对应位置元素的删除中,把对应元素修改为s->sz-1即可,可以在这个函数中直接调用元素删除的函数

//函数功能:顺序表的尾删
void SLpopBack(SeqList* s)
{
	assert((s->sz) > 0);                    //暴力检查顺序表中是否有元素
	//s->sz--;                              //顺序表的尾删,直接让顺序表中的元素个数-1就好
	SLerase(s,s->sz-1);
}

4. 在顺序表中找一个中间位置插入

        这里面要设计一个循环,i从s->sz开始,然后把前面的元素依次拷贝,i不可以=pos,只需要指向pos的后一个元素即可拷贝到pos位置的元素

//函数功能:在顺序表中找一个中间位置插入(包括了暴力检查)
void SLpush(SeqList* s,int pos,DataType x)
{
	assert(pos >= 0 && pos <= s->sz);
	CheckSL(s);
	for(int i = s->sz;i > pos;i--)
	{
		s->data[i] = s->data[i-1];
	}
	s->data[pos] = x;
	s->sz++;
}

5. 顺序表的头插法

        这里可以使用函数中调用函数,在头插函数中调用一个中间插入函数,把位置设置为0即可

//函数功能:头插法
void SlpushFront(SeqList* s,DataType x)
{
	CheckSL(s);
	SLpush(s,0,x);
}

6. 顺序表的尾插法

        这里可以使用函数中调用函数,在尾插函数中调用一个中间插入函数,把位置设置为s->sz即可

//函数功能:顺序表的尾插法
void SLpushTail(SeqList* s,DataType x)
{
	CheckSL(s);
	SLpush(s,s->sz,x);
}

7. 查找元素,并返回位置

        这个其实很简单,就是从位置0开始依次遍历顺序表,只要找到了对应的元素就返回下标即可

//函数功能:查找顺序表中的元素,并且返回其对应的下标 ???
int SLFind(SeqList* s,DataType x)
{
	for(int i = 0;i < s->sz;i++)
	{
		if(s->data[i] == x)
		{
			return i;
		}
	}
	return false;
}

8. 根据位置修改顺序表中的元素的值

        这个是最简单的一个函数,首先要判断函数的位置是否合法(位置要在顺序表中),然后直接把顺序表中对应的位置的值修改为想要的值即可

//函数功能:根据位置修改顺序表中的元素的值
void SLmodify(SeqList* s,int pos,DataType x)
{
	assert(pos >= 0 && pos < s->sz);
	s->data[pos] = x;
}

完整的顺序表实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#define MAX 4
#define DataType int      //把int类型定义为DataType,表示顺序表中的数据,其实什么数据类型都可以重新定义

typedef struct SL{
	DataType* data;             //定义一个指针变量data,用来存储对应的数据
	int sz;                     //定义一个sz变量,用来控制当前的数据个数
	int capacity;               //定义一个capacity变量,用来表示当前顺序表中的容量
}SeqList;

//函数功能:顺序表的中间删除
void SLerase(SeqList* s,int pos)
{
	assert(pos >= 0 && pos < s->sz && s->sz > 0);
	for(int i = pos;i < s->sz-1;i++)
	{
		s->data[i] = s->data[i+1];
	}
	s->sz--;
}

//函数功能:顺序表的头删
void SLpopFront(SeqList* s)
{
	SLerase(s,0);
}

//函数功能:初始化顺序表
void InitSq(SeqList* s)
{
	s->data = (DataType*)malloc(sizeof(DataType)*MAX);
	s->sz = 0;
	s->capacity = MAX;
}

//函数功能:销毁顺序表
void DestorySl(SeqList* s)
{
	free(s->data);                   //解除s->data指向空间的所有权
	s->sz = 0;                       //将当前顺序表的元素个数置为0
	s->capacity = 0;                 //将顺序表的总个数置为0
	s->data = NULL;                  //将s->data指针指向NULL,避免野指针的错误
}

//函数功能:检查顺序表中的容量是否够用
void CheckSL(SeqList* s)
{
	if(s->sz == s->capacity)
	{
		DataType*tmp = realloc(s->data,2*sizeof(DataType)*s->capacity);    //如果顺序表满了,重新申请内存,大小是当前顺序表最大容量的二倍
		if(tmp == NULL)
		{
			perror("realloc error");
		}
		else
		{
			s->data = tmp;
			s->capacity *= 2;
		}
	}
}


//函数功能:顺序表的尾删
void SLpopBack(SeqList* s)
{
	assert((s->sz) > 0);                    //暴力检查顺序表中是否有元素
	//s->sz--;                              //顺序表的尾删,直接让顺序表中的元素个数-1就好
	SLerase(s,s->sz-1);
}

//函数功能:在顺序表中找一个中间位置插入(包括了暴力检查)
void SLpush(SeqList* s,int pos,DataType x)
{
	assert(pos >= 0 && pos <= s->sz);
	CheckSL(s);
	for(int i = s->sz;i > pos;i--)
	{
		s->data[i] = s->data[i-1];
	}
	s->data[pos] = x;
	s->sz++;
}

//函数功能:头插法
void SlpushFront(SeqList* s,DataType x)
{
	CheckSL(s);
	SLpush(s,0,x);
}
//函数功能:顺序表的尾插法
void SLpushTail(SeqList* s,DataType x)
{
	CheckSL(s);
	SLpush(s,s->sz,x);
}

//函数功能:顺序表的遍历
void PrintSL(SeqList* s)
{
	for(int i = 0;i < s->sz;i++)
	{
		printf ("%d ",s->data[i]);
	}
	printf ("\n");
}

//函数功能:查找顺序表中的元素,并且返回其对应的下标 ???
int SLFind(SeqList* s,DataType x)
{
	for(int i = 0;i < s->sz;i++)
	{
		if(s->data[i] == x)
		{
			return i;
		}
	}
	return false;
}

//函数功能:根据位置修改顺序表中的元素的值
void SLmodify(SeqList* s,int pos,DataType x)
{
	assert(pos >= 0 && pos < s->sz);
	s->data[pos] = x;
}

int main (void)
{
	SeqList s;                  //定义一个顺序表变量S
	InitSq(&s);                 //初始化顺序表s,这里要传递变量s的地址,如果只是传值的话改变不了s中的值
	SLpushTail(&s,1);
	SLpushTail(&s,2);
	SLpushTail(&s,3);
	SLpushTail(&s,4);
	SLpushTail(&s,5);
	SLpushTail(&s,6);
	SlpushFront(&s,10);
	SLpush(&s,3,7);
	//SLpopBack(&s);
	SLerase(&s,2);
	SLpopFront(&s);
	SLmodify(&s,2,10);
	PrintSL(&s);
	DestorySl(&s);
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值