数据结构与算法笔记3

链表

数组和链表:
从底层存储结构上来看:数组需要一段连续的内存空间来存储数据,堆内存的要求比较高;链表恰恰相反,他不用连续的一段内存,它可以通过指针指向链表中的下一个元素的位置,从而来进行添加删除等操作。

单链表
链表通过指针将一组零散的内存块串联在一起,吧内存块称为链表的结点,为了可以找到链表的结点的下一个结点,所以每个结点中所存储的除去值之外还有下一个节点的地址,我们把这个记录下一个结点地址的指针叫做后继指针next。单链表中的第一个结点就是头结点,最后一个结点就叫做尾结点,头结点记录了整个链表的基地址,而尾结点指向一个空地址,表示这是链表上的最后一个结点。
链表的插入和删除

在某个节点的后边插入一个元素,就是将此节点的指针指向被插入的节点的地址,被插入节点的指针在指向原有的节点的地址;删除某个节点后边的元素,就是把这个节点的指针直接指向下一个节点的下一个,这样就把原来的节点隔过去了,也就使他不在链表上了。插入和删除操作本身的时间复杂度是O(1).
想要随机访问链表中的某个元素就需要一个一个向后找,他的时间复杂度为O(n)。
循环链表
循环链表就是单链表原先尾结点的指针是指向Null的,但是现在是指向头结点,这样就可以得到一个循环链表。对于处理具有环形结构特点的数据是很合适,

双向链表
双向链表顾名思义就是每个节点应该有两个指向的指针,之前是向后指,相对的,现在应该多了一个向前指的指针,分别叫做前驱指针prev,后继指针next。
删除操作存在两种情况:
删除结点中“值等于某个给定值的结点”:这种情况和之前提到的一样,先找到相应元素的结点,然后再进行删除操作;
删除给定指针指向的结点:删除某个节点q需要知道其前驱结点,而单链表没有前驱结点,双向链表中存储了前驱结点的指针,就可以直接找到他之前的元素进行操作。
双向循环链表

理解指针的含义
将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能够找到这个变量。p->next = q,这个意思是p结点中的next指针存储了q结点的内存地址;另一个p->next = p->next->next,指的是p节点的next指针存储了p结点的下下个节点的内存地址。
警惕内存的丢失
插入节点时一定要注意操作的顺序,要先将插入结点x的next指针指向下一个结点,然后再把前一个结点的next指针指向插入结点;删除节点时要注意释放内存空间

利用哨兵简化实现难度
对于链表来说对头指针、为指针的操作会出现特殊情况,向空链表插入一个结点;以及删除尾结点,这两种情况都与之前的插入删除操作的逻辑是不一样的,可以利用哨兵解决边缘问题
留意边界条件的处理
如果链表为空时,如果链表只包含一个结点时,如果链表只包含两个结点时代码逻辑在处理头结点和尾结点的时候,是否能正常工作?
举例画图,辅助思考
多练多写

记住几个习题,之后有空把这个做一下
单链表反转
链表中环的检测
两个有序的链表合并
删除链表倒数第 n 个结点
求链表的中间结点

关于栈,有着后进先出,先进后出的特点,只允许在一端进行插入和删除操作。
实现一个栈
对栈的操作主要包括两个入栈和出栈,在栈顶插入一个数据,在栈顶删除一个数据。栈可由数组实现,叫做顺序栈、由链表实现,称为链式栈。
时间复杂度,都是在栈顶进行操作,时间复杂度为O(1)
空间复杂度:在进行入栈和出栈操作的过程中基本上只会用到几个变量,所以他的空间复杂度应该为O(1)

栈在括号匹配中的应用

可以用占来解决遗传括号的输入是否合法,用栈来保存未匹配的左括号,从左到右依次扫描字符串当扫描到左括号的时候就压入栈,右括号的时候就需要和栈顶存入的括号进行比较,如果是一对的话就把栈顶的括号出栈,如果不匹配或者栈空了,那么这一串括号就不合法。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页