链表

多功能单链表实现

天大地大妈咪最大 提交于 2020-02-28 01:08:28
功能&指令 1.增加头节点 addHead + value 2.增加特定节点前的节点 addIndex + value + index 3.增加尾节点 addTail +value 4.删除头节点 deleteHead 5.删除特定节点前的节点 deleteIndex +index 6.翻转链表 reverse 7.打印链表 printList 8.清空链表 freeList 9.退出 EOF(Windows Ctrl+Z)(Linux/Unix Ctrl+D) 程序实现 # include <stdio.h> # include <stdlib.h> # include <string.h> typedef struct Node { int val ; struct Node * next ; } List ; List * creatList ( ) { List * head = ( List * ) malloc ( sizeof ( List ) ) ; head -> next = NULL ; return head ; } //Get the node by subscript, the subscript of the head node is 1 //If the node value is successfully obtained, the value

LeetCode 面试题 02.06. 回文链表

孤街浪徒 提交于 2020-02-27 22:51:17
题目链接: https://leetcode-cn.com/problems/palindrome-linked-list-lcci/ 编写一个函数,检查输入的链表是否是回文的。 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题? 思路:快慢指针找中点将链表分为两部分,再将后半段逆链表,再依次比较。 1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * struct ListNode *next; 6 * }; 7 */ 8 9 bool isPalindrome(struct ListNode* head){ 10 if(head==NULL||head->next==NULL) return true; 11 struct ListNode *slow=head,*fast=head; 12 while(fast->next&&fast->next->next){ 13 fast=fast->next->next; 14 slow=slow->next; 15 } 16 struct ListNode *cur=slow,*tmp

数据结构——树

[亡魂溺海] 提交于 2020-02-27 22:43:34
数据结构——树 树其实就是不包含回路的连通无向图。 树的特性: 1)一棵树中的任意两个结点有且仅有唯一的一条路径连通; 2)一棵树如果有nn个结点,则它一定有n−1n−1条边; 3)在一棵树中加一条边将会构成一个回路。 树这种数据结构的用途: 例如:家族的族谱图、公司的组织结构图、书的目录等。 1. 二叉树 二叉树是一种特殊的树。二叉树的特点是每个结点最多有两个儿子。 二叉树用范围最广。一颗多叉树也可以转化为二叉树。 1) 满二叉树 :二叉树中每个内部节点都有两个儿子。满二叉树所有的叶节点都有相同的深度。 满二叉树是一棵深度为h且有2h−12h−1个结点的二叉树。 2) 完全二叉树 :若设二叉树的高度为hh,除了第hh层外,其他层的结点数都达到最大个数,第h层从右向左连续 缺若干个结点,则为完全二叉树。 特点: 由上图发现: 1)如果一棵完全二叉树的父节点编号为KK,则其左儿子的编号是2K2K,右儿子的结点编号为2K+12K+1, 公式总结: 2)已知完全二叉树的总节点数为n求叶子节点个数: 当n为奇数时:(n+1)/2 当n为偶数时 : (n)/2 3)已知完全二叉树的总节点数为n求父节点个数:为:n/2 4)已知完全二叉树的总节点数为n求叶子节点为2的父节点个数: 当n为奇数时:n/2 当n为偶数时 : n/2-1 5)如果一棵完全二叉树有N个结点,那么这棵二叉树的深度为

HashMap?

…衆ロ難τιáo~ 提交于 2020-02-27 19:08:42
HashMap数据结构是什么? JDK1.7 HashMap由数组+链表组成的,JDK1.8 HashMap由数组+链表+红黑树组成的 数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。 =============================================================================== key-value是通过什么方式存储进去的? key使用set集合来存储的,value使用collection来存储的。 =============================================================================== 解释hashcode、取余、去重等操作? 计算hashcode的值: //这是一个神奇的函数,用了很多的异或,移位等运算

什么是数组?

依然范特西╮ 提交于 2020-02-27 18:58:35
今天要介绍的主角就是- 数组 ,数组也是数据呈线性排列的一种数据结构。与前一节中的 链表 不同,在数组中,访问数据十分简单,而添加和删除数据比较耗工夫。这和 什么是数据结构 那篇文章中讲到的姓名按拼音顺序排列的电话簿类似。 数组 如上就是数组的概念图,Blue、Yellow、Red 作为数据存储在数组中,其中 a 是数组的名字,后面 [] 中的数字表示该数据是数组中的第几个数据,该数字也就是 数组下标,下标从 0 开始计数 ,比如 Red 就是数组 a 的第 2 个数据。 那么 为什么许多编程语言中的数组都从 0 开始编号的呢 ?先别急,可以先自己思考下,将会在文末进行讲解。 从图中可以看出来,数组的数据是按 顺序存储 在内存的连续空间内的。 由于数据是存储在连续空间内的,所以每个数据的内存地址(在内存上的位置)都可以通过数组下标算出,我们也就可以借此直接访问目标数据,也就是 随机访问 。 比如现在我们想要访问 Red,如果是链表的话,只能使用指针就只能从头开始查找,但在数组中,只需要指定 a[2],便能直接访问 Red。 但是,如果想在任意位置上添加或者删除数据,数组的操作就要比链表复杂多了。这里我们尝试将 Green 添加到第 2 个位置上。 首先,在数组的末尾确保需要增加的存储空间。 为了给新数据 Green 腾出位置,要把已有数据一个个移开,首先把 Red 往后移。 然后把

剑指offer 面试题25 合并两个排序的链表

你离开我真会死。 提交于 2020-02-27 18:52:57
问题: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则 输入: 两个链表的头结点指针 输出: 合并后的链表头节点指针 思路: 首先,判断两个链表是否为空链表。 然后,比较两个链表的头节点,将头节点小的节点链接到已经合并的链表后。 最后,注意判断是否有链表指向nullptr(到达链表尾部),这时,可以直接将另外一个链表链接到已经合并的链表后。 画龙点睛: 创建一个dummy变量,为了在遍历完成时,利用dummy.next输出合并链表的头节点。 代码: /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { ListNode pDummy(0); ListNode* pMerge = &pDummy; while(pHead1!=nullptr&&pHead2!=nullptr) { if(pHead1->val<=pHead2->val) { pMerge->next=pHead1; pMerge=pMerge->next; pHead1

C++ 链表求环

孤街醉人 提交于 2020-02-27 18:41:51
已知链表中可能存在环,若有环返回环起始节点,否则返回NULL。 //方法一,使用set求环起始节点。 //遍历链表,将链表中节点对应的指针(地址)插入set。 在遍历时插入节点前,需 //要在set中查找,第一个在set中发现的的节点地址 XM代理申请 ,即是链表环的起点。 //Runtime: 24 ms,Memory Usage: 12 MB。 class Solution { public: Solution(){} ~Solution(){} ListNode detectCycle(ListNode head) { std::set node_set; while (head) { if (node_set.find(head)!=node_set.end()) { return head; } node_set.insert(head); head = head->next; } return NULL; } }; /* //方法二:快慢指针。Runtime: 12 ms,Memory Usage: 9.9 MB。 //时间复杂度为O(n) class Solution { public: Solution(){} ~Solution(){} ListNode detectCycle(ListNode head) { ListNode* fast = head;

C++ 链表求环

早过忘川 提交于 2020-02-27 18:40:01
已知链表中可能存在环,若有环返回环起始节点,否则返回NULL。 //方法一,使用set求环起始节点。 //遍历链表,将链表中节点对应的指针(地址)插入set。 在遍历时插入节点前,需 //要在set中查找,第一个在set中发现的的节点地址 XM代理申请 ,即是链表环的起点。 //Runtime: 24 ms,Memory Usage: 12 MB。 class Solution { public: Solution(){} ~Solution(){} ListNode detectCycle(ListNode head) { std::set node_set; while (head) { if (node_set.find(head)!=node_set.end()) { return head; } node_set.insert(head); head = head->next; } return NULL; } }; /* //方法二:快慢指针。Runtime: 12 ms,Memory Usage: 9.9 MB。 //时间复杂度为O(n) class Solution { public: Solution(){} ~Solution(){} ListNode detectCycle(ListNode head) { ListNode* fast = head;

237

一世执手 提交于 2020-02-27 18:14:56
删除链表中的节点 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。 现有一个链表 – head = [4,5,1,9],它可以表示为: 示例 1: 输入: head = [4,5,1,9], node = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 示例 2: 输入: head = [4,5,1,9], node = 1 输出: [4,5,9] 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 说明: 链表至少包含两个节点。 链表中所有节点的值都是唯一的。 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 不要从你的函数中返回任何结果。 /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ void deleteNode ( struct ListNode * node ) { struct ListNode * p = node -> next ; node -> val = p -> val ; node -> next =

剑指Offer

穿精又带淫゛_ 提交于 2020-02-27 17:26:41
题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 思路: 设置快慢指针,都从链表头出发, 快指针每次 走两步 ,慢指针一次 走一步 ,假如有环, 一定相遇于环中某点(结论1)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次 走一步 ,最终相遇于环入口(结论2)。以下是两个结论证明: 两个结论: 1、设置快慢指针,假如有环,他们最后一定相遇。 2、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。 证明结论1 :设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为low一旦进环,可看作fast在后面追赶low的过程,每次两者都接近一步,最后一定能追上)。 证明结论2: 设: 链表头到环入口长度为-- a 环入口到相遇点长度为-- b 相遇点到环入口长度为-- c 则:相遇时 快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。 慢指针路程=a+b 快指针走的路程是慢指针的两倍,所以: (a+b)*2=a+(b+c)k+b 化简可得: a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度 。其中k>=1,所以 k-1>=0