ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

《程序员养成记》第8集 数据结构才是程序的灵魂

2021-04-02 13:34:16  阅读:103  来源: 互联网

标签:Node 养成 header 代码 编程 C语言 程序员 数据结构


如果生活说生活是由各种规则构造,那么在规则之下还觉得生活有趣的无法就是每个有趣的灵魂,编程亦是如此!

#include <stdio.h>

int main() {
	char you_qu = 0;

	printf("你觉得生活有趣吗?(Y/N):");
	you_qu = getchar();

	if (you_qu == 'Y') {
		printf("你应该有一个有趣的灵魂吧!!\n");
	} else if (you_qu == 'N') {
		printf("你灵魂缺少滋养,几乎干渴了!!\n");
	} else {
		printf("你多半没有灵魂了!!\n");
	}

	return 0;
}
你觉得生活有趣吗?(Y/N):Y
你应该有一个有趣的灵魂吧!!

你觉得生活有趣吗?(Y/N):N
你灵魂缺少滋养,几乎干渴了!!

你觉得生活有趣吗?(Y/N):X
你多半没有灵魂了!!

01 数据结构课程

这个课程是在学习了C语言后,接下这个学期要学习的内容。在知道数据结构这门课程后,我才知道,为什么之前学习的C语言像是没有灵魂,必须通过一些死记硬背的方式去记住很多规则,这也是很多同学放弃的理由吧。

我能够坚持下来不是因为我有多么的喜欢死记硬背,相反我是非常不擅长死记硬背的那种人,记得小学、初中因为背课文经常被放学后留下来的悲惨经历,苦不堪言。

只是因为我对其他课程感到无趣,那么我上大学的目的是什么呢?我需要一个上大学的借口,不然我很难再坚持下去了,编程对于我来说唯一的吸引并非编程本身,我和现在的大部分编程小白一样,只是单纯的想做一个黑客,给人一种深沉的神秘感,同时也是一种局部存在感的表达。

为此,我还特意买了一些书《七剑下天山》、《我的黑客女友》等一些看上去与黑客有关的书籍,还非常认真的通读了全书,确实学到了一些东西,但不是编程相关的东西,而只是一些工具的使用。虽然这些书籍,在专业人士的眼里只不过是一些外行人用来装点门面的技艺,没有实质性技术价值,对于初学者的我还是如获至宝。

那么真正的编程又是什么呢?我突然想起,一个月前wtea给出的那道题“堆和栈的区别”,让我无地自容的题目,同时也是让我从自以为的得意时刻跌落深渊的时刻,我将铭记这个时刻,永远不要太高调,因为你所见到的可能只是你的认知范围内的知识。

超出认知,你不知,不是你的错误的,但是过于自满那肯定是要吃亏的。

这是大二第一学期,开始学习数据结构课程后,我终于明白了什么叫井底之蛙了,山外有山,人外有人。如果把编程比喻成乾坤大挪移神功,我目前的水平还在第一重,总共有七重。

数据结构就是第二重神功,从最开始C语言的招式修改修炼上升到对低阶心法的领悟上。

我举个数据结构中比较有意思的一个结构:链表。

假设人的生命是循环的:

a:出生 b:中年危机 c:退休 d:晚年 e:投胎

我们如何使用链表来表示呢?

假设每个阶段都是一个节点,这个节点有一个名字,就是我们定义的阶段名字,为了方便表示,我们给每个阶段对应一个字母a->n,毕竟使用中文写代码不是很美观的,接下来我们需要先定义这个节点的数据结构。

#define MAX_SIZE 32

typedef struct _Node {
	char code;              // 字母代号
	char name[MAX_SIZE];    // 阶段名称
	struct _Node* next;     // 指向下一个节点
} Node;

我们定义完成用来表示一个阶段的数据结构,如上代码应该是一目了然的了,我需要特别说明的next,这个变量是一个指针,其实在计算机里面就是一个内存地址的存在,用来指向下一个阶段的内存地址,他就相当于连接两个阶段之间的那条线,如果没有这条线,我们是没有办法把前后阶段按照一定顺序串联起来的。

其中出现了几个关键字:

  • struct : 结构体类型关键字,表示下面定义的是一个结构体类型,结构体可以把一系列相关的属性放在一个集合中表示,主要解决的是编程中的一个重要问题:内聚,这种代码可以提高代码的可读性,同时减少代码维护难度和成本。

  • typedef: 是定义别名的意思,在本例中,是吧struct _Node重命名为Node,在C语言中如果要定义一个结构体(struct)变量,需要使用struct修饰变量,如果我们重命名后,就只需要使用Node代表了,可以减少代码的冗余度。这种是否方法在C语言中是非常常见的。

  • define : 这表示一个宏定义,在C语言中也叫预编译宏,为啥叫预编译呢?因为他是在编译器执行之前就进行了替换工作,我们看到的代码中的 MAX_SIZE 其实在编译阶段是不存在的,他不是一个变量,连常量都算不上,在本例中只是32的一个代名词,方面代码中进行全局替换,同时减少代码中到处使用硬编码的数字,这样也是为了代码可维护性考虑。也是在C语言中非常常用的编程方式。

需要注意的是C语言都是需要使用“;”分号表示语句的结束的,无论是单行的普通语句,还是定义结构体这种比较长的多行语句,对于编译器来讲,他以分号分割为标记进行语法解析,所以如果缺少分号,编译器会报语法错误,这也是新人最容易犯的错误。我同样在这个错误上重复犯错,最后才能形成条件反射。

接下来,我们需要把一个一个的节点通过代码把他们串联起来,我们把上面的代码放到一起,方便观看。

#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define MAX_SIZE 32

typedef struct _Node {
	char code;              // 字母代号
	char name[MAX_SIZE];    // 阶段名称
	struct _Node* next;     // 指向下一个节点
} Node;

// 初始化链表
Node* init_list() {
	char codes[] = { 'a', 'b', 'c', 'd', 'e' };
	const char *names[5] = { "出生", "中年危机", "退休", "晚年", "投胎" };
	Node* header = NULL;
	Node* p = NULL;
	int i = 0;

	for (i = 0; i < sizeof(codes); i++) {
		if (header == NULL) {
			header = p = (Node*)malloc(sizeof(Node));
		} else {
			p->next = (Node*)malloc(sizeof(Node));
			p = p->next;
		}
		
		p->code = codes[i];
		strcpy(p->name, names[i]);
		p->next = NULL;
	}

	p->next = header;

	return header;
}

// 输出链表
void output(Node* header, int count) {
	Node* p = header;

	while (p != NULL && count > 0) {
		printf("%c:%s->", p->code, p->name);
		p = p->next;
		count--;
	}
}

int main() {
	// 首先我们需要定义一个变量来表示这个循环链表的头
	// NULL在C语言中表示空,这个空其实在内存里面就是0,这个特殊单词,
	// 仅仅是为指针类型准备的,其他类型最好不要使用。
	Node* header = NULL;

	// 接下来,我们要初始节点,并同时把他们串联起来,我们定义一个新的函数来初始化。
	header = init_list();

	// 我们安装顺序输出
	output(header, 10);

	return 0;
}

我们在输出函数ouput中第二个参数,表示输出节点的个数,设置输出10个节点,我们来看看执行结果:

a:出生->b:中年危机->c:退休->d:晚年->e:投胎->a:出生->b:中年危机->c:退休->d:晚年->e:投胎->

可以看到他是一个死循环在执行的。

这就是链表实现的一个生命循环,是不是特别有意思。


02 编程之外的往事

在学习数据结构课程的过程中有一次忘记了去上课,这个教授数据结构的老师是一个中老年老师,非常的严格,缺一次课,就扣10分。

我忘记了上课,当我想起来赶到教室门口时,已经开始点名了,我不敢进去,因为害怕这个老师,同时这么多人看着确实不好进,我在教室门口犹豫很久,最后还是放弃了。

虽然我的上机实验课和课程设计都是满分,最后本课程的分数也只有80分而已,后来我开始反思,上课到底是否重要,我总结的结论是,如果你有自主学习的能力,上课已经不重要了。

但是如果你是要通过考试或者考高分在一些不重要的非专业课上,你就必须的听老师的课,老师会给你划重点,这也是学校惯例,甚至有些课程太复杂,导致大部分人无法及格,可能会重考甚至开卷考试。

这种考试的意义却是没有了,只是一种形式而已,对于一些普通的大学,毕业率可能远远大于学生是否学到东西。

这件事情也奠定后来我厌弃上课的基础情绪,我觉得上课的方式是满足大部分的学习进度的方式,不适合天才,或者不适合在某个方面要求更大进步的人。后来总结发现编程几乎是靠自己的努力,老师的作用几乎没有太大作用,当然那些想通过老师的课程拿高分的同学,虽然没有真材实料,但是确实可以考到高分。与我,与成为优秀的程序员并没有直接关系。

我不是鼓励大家翘课,而是想说明一个问题,自觉性的作用远远大于跟什么老师学习,大学生靠的是自己的意愿,所谓兴趣那只是针对业余选手的乐趣,专业的程序员,需要的是坚持。

这种坚持是日复一日的刻意练习,在学习数据结构的课程结束后,我对C语言的掌握可以说是随心所欲的程度了。

这个课程后,我的C语言代码量有之前预估的4W行,增长到7W行左右。

但是我没有意识到一个问题,那就是重复性问题,重复劳动带来的不是质的变化,让我停留在一个自以为可以自己控制的世界里洋洋得意,对于常见的课程设计都可以通过同样的套路,复制粘贴代码,快速形成一个课程设计,在这个过程,我成了课程设计生成机器,解决本班级一半人的课程设计难题。

中间发生了一些有趣事情,请看下回分解。

标签:Node,养成,header,代码,编程,C语言,程序员,数据结构
来源: https://blog.csdn.net/tencupofkaiwater/article/details/115396290

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有