学会铁砂掌,手撕顺序表(内含源码)

目录

文章目录

前言

一、手撕顺序表

1.铁砂掌总纲

2.动态数据结构

3.实现

1.1:劈天

1.2:劈地 

1.3:劈神 

总结


前言

        练会铁砂掌,手撕顺序表

        知识点:需要基本上对于C语言有一点的了解

        顺序表分为静态顺序表和动态顺序表,重点说明动态顺序表。

        如铁砂掌招数有问题,或可以优化,望各位大侠进行斧正。(ง •̀_•́)ง(ง •̀_•́)ง(ง •̀_•́)ง


提示:以下是本篇文章正文内容,下面案例可供参考

一、手撕顺序表

1.铁砂掌总纲

        我们知道顺序表属于数据结构,而数据结构的作用无非就四个字(增删查改);在不同的场景使用不同的数据结构类型,如果数据结构有等级的话,那么顺序表是进入数据结构的大门阶梯,拿下顺序表才能触摸到数据结构的大门,也是筑起数据结构大厦的地基。

        数据结构分为:线性数据结构、非线性数据结构、特殊数据结构。而今天要手撕的就是线性数据结构下面的小喽啰。干掉小喽啰让我们逐步升级。

        顺序表简单来说就是一个数组,它通过与结构体相结合进行实现。一下就是顺序表的两种不同的状态和定义,如果C语言结构体学的还可以的话那么静态顺序表就不用多说了就是结构体。如果静态看不懂的话,需要对结构体进行补一下,因为在数据结构的时间里,不会结构体和指针,就相当于修仙没有灵气。

// 静态顺序表 -- 非常不好用,开多了浪费,开少了不够
//struct seq_list
//{
//	int a[10]; //
//	int size;
//};

// 动态顺序表 -- 按需申请,不够了扩容
typedef struct seq_list
{
	int size; // 有效数据个数
	int capacity; // 现在空间容量的大小
	int* p; //一个int类型的指针,指向一个空间
}sl;

2.动态数据结构

        顺序表就相当于一个数组,动态顺序表相当于一个可以变大的数组;而所要实现的无法就是增删查改。所以我们先声明一下所需要的东西。 对于相应的函数也有注释

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// 顺序表
// 用一段物理地址连续的依次性的储存数据元素的线性结构
typedef int sl_data_type; //对顺序表的类型名称进行定义,好处是想存字节换成 char就可以了
#define INIT 4 //初始化的容量
// typedef通常是对类型进行重定义, #define 中的 I 通常是定义常量或者宏函数

// 动态顺序表 -- 按需申请,不够了扩容
typedef struct seq_list
{
	int size; // 有效数据个数
	int capacity; // 现在空间容量的大小
	sl_data_type* p; //一个int类型的指针,指向一个空间
}sl;

// 数据结构无非是 增删查改
void seq_init(sl* ps); //初始化
void seq_destroy(sl* ps); //删除
void seq_push_back(sl* ps, sl_data_type x); //尾插
void seq_pop_back(sl* ps); //尾删
void seq_push_front(sl* ps, sl_data_type x); //头插
void seq_pop_front(sl* ps); //头删
void seq_push_insert(sl* ps, int pos, sl_data_type x);//某个位置插入
void seq_pop_insert(sl* ps, int pos);//某个位置删除
void seq_printf(sl* ps); //打印
void seq_check(sl* ps);//扩容

3.实现

        我们先定义一个结构体,定义好之后一个结构体我们要传入结构体的地址,当我们传s的话我们需要进行拷贝结构体的数据,拷贝完之后进行压栈,当一个结构体数据过大,压栈所使用的空间和时间也会变大,但如果我们传&s,它可以通过指针直接指向结构体,所以当我们进行结构体传参的时候首选地址传参。

test_seqlist() 
{
	sl s; //开辟了结构体变量 s
	seq_init(&s); // 为什么传地址
}

int main()
{
	test_seqlist(); // 顺序表
	return 0;
}

        首先我们需要对它进行初始化,我们把指针所指向的空间想象成一个数组,这个数组刚开始什么都没有,我们在根据malloc函数对p指向的类型空间开辟内存,当开辟完内存之后我们还有判断一下内存是否开辟成功。而 size 我们可以看作数组的下标。 capacity看作数组空间的大小。

#define _CRT_SECURE_NO_WARNINGS
#include "seq_list.h" //声明自己创建的头文件

void seq_init(sl* ps) //初始化
{
	ps->p = NULL; //将指针初始化为空
	ps->p= (sl_data_type*)malloc(sizeof(sl_data_type) * INIT); //单个对象的大小*所要对象的个数
	if (ps->p == NULL)
	{
		perror("malloc fail"); // 若为空指针开辟失败
		return;
	}
	ps->size = 0; //存了多少数据
	ps->capacity = INIT; // 先开辟一点空间
}

         古语有云:有借有还,再借不难。当我们不用顺序表的时候就要把它还回去。这里的还回去是将整个顺序表全部给换回去,因为free释放的是整块空间。

void seq_destroy(sl* ps) //空间不用了要归还
{
	free(ps->p);
	ps->p = NULL;
	ps->capacity = ps->size = 0;
}

         初始化之后我们放进去了四个类型大小的空间,但是如果我们要放进去五个数据,这时候只有四个数据是不行的,怎么办? 扩容,没有空间好说给它空间不就完事了。但是问题又开了,怎么扩容呢?需要使用C语言中的realloc函数进行扩容。

void seq_check(sl* ps) //扩容
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		sl_data_type* tmp = (sl_data_type*)realloc(ps->p, ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("reallpc fail");
			return;
		}
		ps->capacity *= 2; // 扩容成功,可用容量数*2
	}
}

        练铁砂掌所需要的洗手丹已经配置好,所需要的材料也配置完成。我们已经能够进行开辟空间,空间不够给它空间,如果不需要将空间还给操作系统。让我们开始练铁砂掌。

        铁砂掌共有三式,分别为:劈天,劈地,劈神。

1.1:劈天

        下面让我们开始练铁砂掌的第一式:劈天。

        对于顺序表数据的插入,我们先来搞定头插,什么是头插呢?顾名思义,从首位插入,如果我们插入1,2,3,4,5。那么顺序表里面的顺序就是 5,4,3,2,1。实现头插就要定义一个函数,依靠这个函数实现头插,那么实现头插,我们要有一个要插入数据的参数,和指向顺序表地址的参数。通过这个参数进行实现。断言和扩容这个就不用说了。插入第一个不就是将数据依次向后面放,放完之后再将要插入的数据放进第一个位置空间。放到第一个空间,后面数据该怎么移动呢?我们将最后一个数据向后放,不断的对数据进行覆盖。

321
4321
54321
void seq_push_front(sl* ps, sl_data_type x) 
{
	assert(ps);
	void seq_check(sl * ps);//扩容
	int end = ps->size - 1; //要插入对象下标
	while (end >= 0) //循环停止代表找到了最前面的地址了
	{
		ps->p[end + 1] = ps->p[end];
		--end;
	}
	ps->p[0] = x;
	ps->size++; //插入完成之后数组元素多了一位要加进去
}

// 第二种方式
front(sl* ps, sl_data_type x)
{
	assert(ps);
	void seq_check(sl * ps);//扩容
	int cmp = ps->size + 1;
	while (cmp)
	{
		ps->p[cmp] = ps->p[cmp-1];
		cmp--;
	}
	ps->p[0] = x;
	ps->size++;
}

        头插我们学会了,不就是向里面放数据吗?下面我们学习它相反的一面,从头删数据。万物有阴有阳,我们的招数也不例外,插入数据是阳,删除数据就是阴。

        当我们进行头删的时候,第一个点是什么?里面要有数据,如果没有数据,我们可以不提醒直接退出,也可以提醒告诉他没有数据不用删除了。根据不同场景进行使用。删除就是将前面的数据进行覆盖,size-- 使得访问不了最后一个数据。这样就完成了头删。

        注意:向前覆盖后面的数据还再,只不过当我们size进行-1的时候访问不到数据了。当我们再插入数据。后面的数据会被覆盖,不会有任何的印象

54321
4321size--(1)
321size--(1)(1)
void seq_pop_front(sl* ps) //头删
{
	assert(ps);
	assert(ps->size > 0);//当表为空就不用再删了
	int begin = 1; //当这个数组下标为0的时候就不能在删了
	while (begin < ps->size)
	{
		ps->p[begin - 1] = ps->p[begin]; // 每次向前一位
		begin++;
	}
	ps->size--; //删去一位下标也要-1
}

1.2:劈地 

        铁砂掌已经登堂入室了。下面我们就来学习第二式,劈地。

        劈天是进行首位的插入和删除,劈地正好相反,是尾部的插入和删除。学会劈天,劈地真是轻轻松松,size在输入数据的时候会++所以,空间永远会多一个。我们只需要在指针size位置上进行放入数据即可。

1
12
123
void seq_push_back(sl* ps, sl_data_type x)
{
	assert(ps);
	void seq_check(sl * ps);//扩容
	ps->p[ps->size] = x;//我们将p指向的空间看作下标为0的数组,size为下标,又因为size在结构体里面
	//所以ps->size代表size的数字
	ps-> size++;
}

        下面就是尾删 ,这个更简单,看图,尾删将size--不就行了。要注意这是一整块空间,但删除一个数据不能free。

12345
1234
123

void seq_pop_back(sl* ps)
{
	assert(ps->p > 0); //大于0说明还能继续走,等于0 结束了
	// ps->p[ps->size - 1] = 0; //赋值成0是没有意义的
	ps->size--;
	// 这里不能free空间
}

1.3:劈神 

        各位,我们现在学会了两招,下面就让我们学会最后一招,然后撕碎顺序表。

        我们学会了,头插,头删。那么如果我要在某一个位置插入或者删除怎么办。

比如

12
132
1342

        我们坑定需要构造一个函数,那么这个函数该怎么构造呢?首先我们要传插入的数据,传指针这都是上面的东西 。那么我们要在第二个位置插入,是不是要告诉函数,我在什么位置插入,插入X位置,传进入X。这包含了头插。首先判断传进来的不是个空指针。然后不能是头插和尾插我们将要插入位置向后移动,在将数据插入到这个位置中

        

        注意向后覆盖数据,例子中2这个数据没有被删除,只不过我们再后面将这个位置的数据覆盖了

        int end = ps->size - 1; 这里注意,size位置是没有数据的,所以我们要将它-1获取有效数据。当移动到pos指定位置就不用再向前覆盖了。我们给一个end接收这个位置是防止size变动。

123起始地址
1223向后覆盖数据
1423在指定位置插入
void seq_push_insert(sl* ps, int pos, sl_data_type x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size); //不能插入不存在的位置
	void seq_check(sl * ps);//是否需要扩容
	int end = ps->size - 1; //上一个数组的元素 
	while (end >= pos) //pos占据了end的位置,所以不能 >= 
	{
		ps->p[end + 1] = ps->p[end];//将数据向后移动
		--end;
	} 
	ps->p[pos] = x;
	ps->size++; //插入完成之后数组元素多了一位要加进去
}

         再指定位置插入数据完成了。那么是不是还要学会再指定位置删除数据。

        我相信这个时候有一些小伙伴就不想看了。怎么还有啊。坚持住,这是最后一式的下半式。学会了,铁砂掌就算练成了。这个前面断言和插入一样

        

1234起始地址
134size--
14size--

         这个代码应该不用多说了。注释说的很清楚了。

void seq_pop_insert(sl* ps, int pos)
{
	assert(ps);
    assert(pos >= 0 && pos < ps->size); //不能删除不存在的位置
	int begin = pos+1;//删除pos下标的数据,将这个数据向前覆盖即可
	while (begin < ps->size)//向前覆盖数据
	{
		ps->p[begin - 1] = ps->p[begin];
		begin++;
	}
	ps->size--;

总结

        截止到现在我们的铁砂掌算是成功练成了。这是一个成功,迈入数据结构大门的第一步,还没进行。需要我们举行努力。总结就是,顺序表是以一个结构体来创建一个类似数组的空间,只不过这个空间可以变大。铁砂掌是基础,为了日后降伏数据结构这条龙,学会终极掌法,降龙十八掌打下的基础。

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在铸造造型过程中,铁砂比是指铸造模具中铁砂的质量与铸件质量的比例。降低铁砂比可以减少铸造成本,提高铸件质量和使用寿命。 要降低铸造造型铁砂比,可以考虑以下几种方法: 1. 优化铸造工艺设计:在设计铸造工艺时,可以通过减小铸件的体积、优化模具设计、采用低砂比铸造方法等来降低铁砂比。 2. 选择高品质的铸造砂:铁砂的质量和规格都会影响铸造造型的铁砂比。选择高品质的铸造砂可以减少铸造中的砂浆损失,降低铁砂比。 3. 加强砂型维护:砂型的维护对于降低铸造造型铁砂比也很重要。在铸造过程中,应定期检查砂型的磨损情况,及时修补或更换砂型,以保证砂型的质量和使用寿命。 4. 加强砂型预流动:砂型预流动是指在铸造过程中,将砂型中的砂浆预先流动到铸件内部,以便铸件内部的砂浆填满。 ### 回答2: 降低铸造造型铁砂比是为了提高铸件的成型质量和减少铸件缺陷的发生率。以下是一些降低铸造造型铁砂比的方法: 1. 优化浇注系统:合理设计浇注系统,包括浇注口、浇注道和浇注孔的尺寸和位置,以确保铁液的均匀分布和顺利流动,从而减少铸造造型铁砂的用量。 2. 提高砂型强度:选择合适的砂型材料,并通过合理添加添加剂、控制砂型固化时间和砂型干燥处理等措施,提高砂型的强度和抗压能力,减少铁液渗透砂型的现象,从而降低铸造造型铁砂比。 3. 降低铁液温度:降低铁液的浇注温度,减少铁液与砂型接触时的脉冲效应,从而降低砂芯的消耗。 4. 优化铸件结构:通过优化铸件的结构设计,减少出现过厚或过薄的部分,降低浇注过程中的金属流动阻力,降低铸造造型铁砂比。 5. 加强铸造工艺控制:保持合适的浇注速度和流动方式,合理控制浇注过程中的温度和湿度,缩短浇注时间,减少废品率,降低铸造造型铁砂比。 6. 定期维护和更换设备:定期检查和维护铸造设备,确保设备的正常运行状态,提高设备的效率和稳定性,降低能源消耗和材料损耗,从而降低铸造造型铁砂比。 总之,通过优化工艺控制、改进砂型和结构设计、合理选材、维护设备等多方面的综合措施,可以有效地降低铸造造型铁砂比,提高铸件的质量和生产效率。 ### 回答3: 降低铸造造型铁砂比是提高铸件质量和生产效率的重要措施。下面我将简要介绍一些方法: 1. 选择合适的铸造造型材料:通过优化铸造造型材料的配比和选择合适的填充材料,可以减少铁砂的使用量。采用高品质的造型材料,如钢铁砂等,可以减少砂芯缺陷和表面缺陷的产生。 2. 优化铸造工艺参数:合理调整铸造工艺参数,例如铸造温度、浇注速度、压力等,可降低铁砂的比例。适当提高浇注温度和压力可以改善铸件的充填性和凝固性,减少砂芯和渗漏的风险。 3. 提高模具制造技术:采用先进的数控加工技术和模具制造工艺,可以实现更精确的模具结构和尺寸,减少铁砂的浪费。合理设计模具的结构,避免过度浪费砂芯,提高铸件的成型效率。 4. 引进现代化铸造设备:采用先进的铸造设备,如高效自动造型线、快速固化砂等,可以减少铁砂的使用量。这些设备能够实现高速铸造,提高生产效率,同时减少不必要的砂芯损耗。 5. 加强铸造工艺管理:优化铸造工艺管理,建立严格的质量控制制度,有效控制铁砂比。通过对铁砂的使用情况进行评估和分析,及时调整工艺,减少浪费和缺陷的发生。 综上所述,降低铸造造型铁砂比需要从材料选择、工艺参数调整、模具制造技术、设备引进和工艺管理等方面进行综合考虑和改进。只有通过不断的优化和创新,才能够实现降低铁砂比的目标,提高生产效率和产品质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值