链表

从尾到头打印链表

六眼飞鱼酱① 提交于 2020-03-22 10:58:50
题目要求 输入一个链表,按链表从尾到头的顺序返回一个ArrayList。 算法实现 题目比较简单,直接遍历链表,每次将新的元素插入到数组的第一个元素之前,或者直接插入到数组中,然后调用reverse方法进行反转。 代码 # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 返回从尾部到头部的列表值序列,例如[1,2,3] def printListFromTailToHead(self, listNode): a = [] while listNode != None: a.insert(0, listNode.val) listNode = listNode.next return a 来源: https://www.cnblogs.com/isshpan/p/12544386.html

jdk1.8 HashMap扩容原理详解

老子叫甜甜 提交于 2020-03-22 07:14:18
JDK1.7中,resize时,index取得时,全部采用重新hash的方式进行了。JDK1.8对这个进行了改善。 以前要确定index的时候用的是(e.hash & oldCap-1),是取模取余,而这里用到的是(e.hash & oldCap),它有两种结果,一个是0,一个是oldCap, 比如oldCap=8,hash是3,11,19,27时,(e.hash & oldCap)的结果是0,8,0,8,这样3,19组成新的链表,index为3;而11,27组成新的链表,新分配的index为3+8; JDK1.7中重写hash是(e.hash & newCap-1),也就是3,11,19,27对16取余,也是3,11,3,11,和上面的结果一样,但是index为3的链表是19,3,index为3+8的链表是 27,11,也就是说1.7中经过resize后数据的顺序变成了倒叙,而1.8没有改变顺序。 原理: 我们使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。看下图可以明白这句话的意思,n为table的长度,图(a)表示扩容前的key1和key2两种key确定索引位置的示例,图(b)表示扩容后key1和key2两种key确定索引位置的示例,其中hash1是key1对应的哈希与高位运算结果。 元素在重新计算hash之后

leetcode 2. 两数相加

落花浮王杯 提交于 2020-03-22 03:56:44
题目: 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/add-two-numbers 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 解法: 来源: https://www.cnblogs.com/chenia/p/12543886.html

C#实现顺序表

主宰稳场 提交于 2020-03-22 03:07:45
这几天需要实现各种数据结构(泛型).主要实现线性表和链表。 线性表是由n(n>=0)个相同类型的数据元素构成的有限序列。除第一个元素外,其余元素只有一个直接前驱;除最后一个元素外,其余元素只有一个直接后继。 顺序表是把表中元素一个接一个地放进一快地址连续的空间,因此顺序表的实现有数组来完成。 由于这次需要实现多种数据结构,各种数据结构都有相同的方法,比如求长度,清空等。因此定义一个公共接口: namespace DateStructrues { public interface IDS<T> { int Count { get;} //求长度 void Clear(); //清空操作 bool IsEmpty{get;} //判断线性表是否为空 } } 线性表接口: namespace DateStructrues.Lists { interface IListDS<T> : IDS<T> { void Append(T item); //附加操作 void Insert(T item, int index); //插入操作 T Delete(int index); //删除操作 T GetElement(int index); //取表元 int Locate(T value); //按值查找 } } 实现顺序表: using System; namespace

内存池

元气小坏坏 提交于 2020-03-21 19:57:59
http://blog.csdn.net/neustar1/article/details/7478311 利用C/C++开发大型应用程序中,内存的管理与分配是一个需要认真考虑的部分。 本文描述了内存池设计原理并给出内存池的实现代码,代码支持Windows和Linux,多线程安全。 内存池设计过程中需要考虑好内存的分配与释放问题,其实也就是空间和时间的矛盾。 有的内存池设计得很巧妙,内存分配与需求相当,但是会浪费过多的时间去查找分配与释放,这就得不偿失; 实际使用中,我们更多的是关心内存分配的速度,而不是内存的使用效率。基于此,本文按照如下思想设计实现内存池。 主要包含三个结构:StiaticMemory, MemoryChunk和MemoryBlock,三者之间的关系如下图所示: 1.内存的分配: (1)如果分配大小超过1024,直接采用malloc分配,分配的时候多分配sizeof(size_t)字节,用于保存该块的大小; (2)否则根据分配大小,查找到容纳该大小的最小size的MemoryChunk; (3)查找MemoryChunk的链表指针pList,找到空闲的MemoryBlock返回; (4)如果pList为NULL,临时创建MemoryBlock返回; (5)MemoryBlock头部包含两个成员,pChunk指向的所属的MemoryChunk对象,size表明大小

常见C++内存池技术

三世轮回 提交于 2020-03-21 19:51:22
原文: http://www.cppblog.com/weiym/archive/2013/04/08/199238.html 总结下常见的C++内存池,以备以后查询。 应该说没有一个内存池适合所有的情况, 根据不同的需求选择正确的内存池才是正道. (1) 最简单的固定大小缓冲池 适用于频繁分配和释放固定大小对象的情况, (2) dlmalloc 应该来说相当优秀的内存池, 支持大对象和小对象,并且已被广泛使用。到这里下载: ftp://g.oswego.edu/pub/misc/malloc.c 关于dlmalloc的内部原理和使用资料可以参考: 内存分配器dlmalloc 2.8.3源码浅析.doc (3) SGI STL 中的内存分配器( allocator ) SGI STL 的 allocator 应该是目前设计最优秀的 C++ 内存分配器之一了,它的运作原理候捷老师在《 STL 源码剖析》里讲解得非常清楚。基本思路是设计一个 free_list[16] 数组,负责管理从 8 bytes 到 128 bytes 不同大小的内存块( chunk ),每一个内存块都由连续的固定大小( fixed size block )的很多 chunk 组成,并用指针链表串接起来。比如说 free_list[3]->start_notuse->next_notuse->next

面试题24:反转链表(C++)

荒凉一梦 提交于 2020-03-21 10:35:57
题目地址: https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/ 题目描述 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。 题目示例 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 解题思路 双指针: 使用双指针pre和cur,分别表示当前节点的前一个结点和当前遍历的节点。具体操作定义临时指针tmp,用于存放当前指针cur所指的下一节点,即tmp = cur->next,然后让当前指针cur指向pre,再将cur的值交予pre,最后,将tmp赋值给cur,进行下一轮操作,直到cur到链表尾部。 递归: 使用递归函数递归到链表的最后一个节点,将该节点作为反转后链表的头节点,然后,在每次函数返回过程中,让 当前节点的下一节点的next指向当前节点 ,同时,让当前节点的next指向空,从而实现链表的反转操作。 参考文章: https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/solution/fan-zhuan-lian-biao-yi-dong-de-shuang-zhi-zhen-jia/ 程序源码 双指针 /** * Definition for singly-linked

LeetCode | 19. 删除链表的倒数第N个节点

你说的曾经没有我的故事 提交于 2020-03-21 09:23:54
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5. 说明: 给定的 n 保证是有效的。 进阶: 你能尝试使用一趟扫描实现吗? 解法: 老实用快慢指针,快指针先走n步,然后快慢一起走,直到快指针走到最后,要注意的是可能是要删除第一个节点,这个时候可以直接返回 head -> next class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(!head | !head -> next) return NULL; ListNode * fast = head, *slow = head; for(int i = 0; i < n; i++){ fast = fast -> next; } if(!fast){ return head -> next; } while(fast -> next){ fast = fast -> next; slow = slow -> next; } slow -> next = slow -> next -> next; return head; } }; 来源: https://www.cnblogs

链表操作,涉及到链表首节点指针变动的函数,即使形参包含首节点指针,必须返回首节点指针,原因不得而知

混江龙づ霸主 提交于 2020-03-20 12:52:43
1 //链表操作,涉及到链表首节点指针变动的函数,即使形参包含首节点指针,必须返回首节点指针,原因不得而知 2 # include<stdio.h> 3 # include<stdlib.h> 4 struct Student 5 { 6 int num; 7 struct Student* next; 8 }; 9 struct Student* p; 10 int main() 11 { 12 struct Student*p1; 13 int n; 14 scanf("%d",&n); 15 16 int len(struct Student*); 17 struct Student* create(int); /*这里不能用void create(struct Student*,int); 18 因为创建链表涉及到链表首元素指针的变动,会出现错误,原因未解;*/ 19 20 struct Student* insert(struct Student*,struct Student*,int); /*不能用void insert(struct Student*,struct Student*,int); 21 往链首插元素会涉及到链表首节点指针变动,从而引发错误*/ 22 23 24 struct Student* del(struct Student*,int); /

剑指Offer(链表)-删除链表中重复的节点

♀尐吖头ヾ 提交于 2020-03-20 12:25:11
  (删除链表中重复的节点) 题目描述: 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5    解题思路: 这里的重复的节点不保留是将只要重复了的节点都要删除掉,所以考虑利用哈希set的方法,先进行重复性的判断,将重复的元素加入到哈希set中去,然后将重复的元素删除。   利用到了两个指针pre和cur,来表示前一个节点和当前节点。 /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ import java.util.*; public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead == null){ return null; } //先找出相同节点存入哈希set中 HashSet<Integer> set = new HashSet<>(); ListNode pre = pHead; ListNode cur = pHead.next; while(cur != null){ if(cur.val