数据结构/算法
-
链表
链表的插入删除,单链表和双向链表
反转链表(逆序输出链表)、链表是否有环、取链表的最后k个数
-
hash表
hash表的原理
解决冲突的策略:开放地址法、链表法、建立公共溢出区
hash表相关的算法题(大数据 查找)
//建立一个简单的hash表 typedef struct node { int value; struct node *next; }NODE; typedef struct hash { int size; NODE **list; }HASH; //初始化 HASH *HashInit(int size) { if (size <= 0) return NULL; HASH *hash = (HASH*)malloc(sizeof(HASH)); if (NULL == hash) return NULL; hash->size = size; hash->list = (NODE**)malloc(sizeof(NODE*) * hash->size); if (NULL == hash->list) { free(hash); hash = NULL; return NULL; } int i; for (i = 0; i < size; i++) { hash->list[i] = (NODE*)malloc(sizeof(NODE)); hash->list[i]->next = NULL; } return hash; } //查找 NODE *HashFind(HASH *hash, int key) { NODE *list = hash->list[HashFun(key, hash->size)]; NODE *node = list->next; for (;NULL != node && node->value != key; node = node->next); return node; } //插入 void HashInstert(HASH* hash, int key) { if (NULL != HashFind(hash, key)) return; NODE *node = (NODE*)malloc(sizeof(NODE)); if (NULL == node) return; NODE *list = hash->list[HashFun(key, hash->size)]; node->value = key; node->next = list->next; list->next = node; }
-
树
二叉树:
二叉树的前序、中序、后序遍历(递归和不递归写法)
求二叉树的高度、宽度(层次遍历)
二叉查找树:左子树节点小于根节点,右子树节点大于根节点,左右子树分别为二叉排顺序树(左:降序,右:升序)
红黑树:一种平衡二叉查找树,当根节点足够大(小)时可能导致左(右)子树太长,使查找效率变低,所以引入了红黑树,最长路径不大于最短路径的2倍
特性: 1.每个结点或是红色的,或是黑色的
2.根节点是黑色的
3.每个叶结点(NULL)是黑色的
4.如果一个结点是红色的,那么他的两个子结点都是黑色的
5.对于每个结点,从该结点到其所有后代叶结点的简单路径上,包含相同数目的黑色结点
http://www.360doc.com/content/18/0904/19/25944647_783893127.shtml
B和B+树(数据库索引):
B+ 树的优点在于:由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子节点上关联的数据也具有更好的缓存命中率;B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
B树优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。下面是B 树和B+树的区别图:
-
排序算法
各个排序算法的实现和应用、稳定性、复杂度分析
https://blog.youkuaiyun.com/hellozhxy/article/details/79911867
-
单例模式
单例模式的两种写法(懒汉式、饿汉式)线程安全性
//饿汉 线程安全 class singleton{ private: singleton(); public: singleton *getSingleton() { static singleton s; return &s; } } //懒汉 多线程下不安全 class singleton{ private: singleton(); singleton *s; public: singleton *getSingleton() { if(s == NULL) s = new singleton(); return s; } }//可改进 加锁
-
字符串问题
实现strcpy()、strcmp()、strcat()、memcpy()
char* strcpy(char* dst, const char* src) //有一种地址重叠的情况,参考memcpy { if(dst == NULL || src == NULL) return NULL; char* ret = dst; while((*dst++ = *src++) != '\0'); return dst; } int strcmp(const char* str1, const char* str2) { while(*str1 == *str2 && *str1 != '\0') { ++str1; ++str2; } return *str1 - *str2; } char* mstrcat(char* dst, const char* src) { char* ret = dst; while (*dst != '\0') ++dst; while ((*dst++ = *src++) != '\0'); return dst; } void* mmemcpy(void* dst, const void* src, size_t size) { if (dst == NULL || src == NULL) return NULL; char* pdst = (char*)dst; if (pdst > src && pdst < src + size) //重叠 { pdst = pdst + size - 1; src = src+ size - 1; while (size--) *pdst-- = *src--; } else //无重叠 { while (size--) *pdst++ = *src++; } return dst; }
---------------------------------------------------------------- 更新 ------------------------------------------------------------------------------------------
快排的思想?实现?复杂度?可以怎样优化?
基本思想(分治法)是选择一个基数(默认第一个数),通过一次遍历使其分成两部分,其中左边的数小于基数右边的数大于基数,在将左右部分分别进行快排,重复此步骤直到整个数据有序
平均复杂度为O(nlogn),最坏情况是O(n^2)
快排的优化主要是在对基数的选择上:1、随机选取基数 2、取数组最左、最右、中间的数比较交换
动态规划的本质?
动态规划通过把原来较复杂的问题递归的分解为一组较简单的子问题,并通过存储每个子问题的解,使得每个子问题只计算一次就可以解决原问题的思想。这里的某一类问题通常情况下是指某些最优化问题。这类问题可以有很多可行解,每个解都有一个值 ,我们希望寻找具有最优值(最小值或最大值)的解。
https://www.zhihu.com/question/23995189/answer/35324479
SQL语句的优化?
实践中如何优化MySQL?
优化SQL的语句和索引
优化SQL表结构:尽量满足BCNF、选用字段长度最小、尽可能使用NOT NULL
添加适当的索引(index)[四种:普通索引,主键索引,唯一索引,unique,全文索引]
对mysql配置优化[配置最大并发数,my.ini调整缓存大小]
定时的去清楚不需要的数据,定时进行碎片整理
什么情况下设置了索引但无法使用?
https://www.jianshu.com/p/d55527de337a
数据库索引的底层实现原理和优化?