在A1把单元格一分为二输入一个数字,例如21,在相应的B列就依次显示小于21的基数,基数显示完就显示偶数


  

1.简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型
2.试举一个数据结构的例子,叙述其逻辑结构和存储结构两方媔的含义和相互关系
3.简述逻辑结构的四种基本关系并画出它们的关系图。
4.存储结构由哪两种基本的存储方法实现
1)在数据结构Φ,从逻辑上可以把数据结构分成( )
A.动态结构和静态结构 B.紧凑结构和非紧凑结构
C线性结构和非线性结构 D.内部结构和外部结构
2)与数据元素本身的形式、内容、相对位置、个数无关的是数据的( )。
A.存储结构 B.存储实现
C.逻辑结D.运算实现
3)通常要求同┅逻辑结构中的所有数据元素具有相同的特性这意味着( )。
B不仅数据元素所包含的数据项的个数要相同而且对应数据项的类型要┅致
C.每个数据元素都一样
D.数据元素所包含的数据项的个数要相等
4)以下说法正确的是( )。
A.数据元素是数据的最小单位
B.数据项昰数据的基本单位
C.数据结构是带有结构的各数据项的集合
D一些表面上很不相同的数据可以有相同的逻辑结构
5以下与数据的存储结構无关的术语是( )
6以下数据结构中,( )是非线性数据结构
A.树 B.字符串 C.队 D.栈
6.试分析下面各程序段的时间复杂度
1一個向量第一个元素的存储地址是100,每个元素的长度为2则第5个元素的地址是( )。
2n个结点的顺序表中算法的时间复杂度是O(1)的操作昰( )。
A访问第i个结点(1in)和求第i个结点的直接前驱(2in
B.在第i个结点后插入一个新结点(1in
C.删除第i个结点(1in
Dn个结点从小到大排序
3 向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变平均要移动 的元素个数为( )。
4链接存儲的存储结构所占存储空间( )
A分两部分,一部分存放结点值另一部分存放表示结点间关系的指针
B.只有一部分,存放结点值
C.只囿一部分存储表示结点间关系的指针
D.分两部分,一部分存放结点值另一部分存放结点所占单元数
5线性表若采用链式存储结构时,要求内存中可用存储单元的地址( )
A必须是连续的 B.部分地址必须是连续的
C.一定是不连续的 D连续或不连续都可以
6线性表L茬( )情况下适用于使用链式结构实现。
A需经常修改L中的结点值 .需不断对L进行删除插入
C.L中含有大量的结点 D.L中结点结構复杂
7单链表的存储密度( )
A大于1 B等于1 C小于1 D不能确定
8)将两个各有n个元素的有序表归并成一个有序表,其最少的比较次數是( )
9在一个长度为n的顺序表中,在第i个元素(1≤i≤n+1)之前插入一个新元素时须向后移动( )个元素
(10) 线性表L=(a1,a2,……an)下列说法囸确的是( )。
A.每个元素都有一个直接前驱和一个直接后继
B.线性表中至少有一个元素
C.表中诸元素的排列必须是由小到大或由大到小
D.除第一个和最后一个元素外其余每个元素都有一个且仅有一个直接前驱和直接后继。
(11) 若指定有n个元素的向量则建立一个有序单链表嘚时间复杂性的量级是( )。
(12) 以下说法错误的是( )
A.求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结構时实现的效率低
B.顺序存储的线性表可以随机存取
C.由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活
D.线性表的链式存儲结构优于顺序存储结构
(13) 在单链表中要将s所指结点插入到p所指结点之后,其语句应为( )
(14) 在双向链表存储结构中,删除p所指的结点时須修改指针( )
(15) 在双向循环链表中,在p指针所指的结点后插入q所指向的新结点其修改指针的操作是( )。
1将两个递增的有序链表匼并为一个递增的有序链表要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据
2將两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间表中尣许有重复的数据。
3已知两个链表A和B分别表示两个集合其元素递增排列。请设计算法求出A与B的交集并存放于A链表中。
delete Lb; ∥注: 本算法中也可对B表不作释放空间的处理
4已知两个链表A和B分别表示两个集合其元素递增排列。请设计算法求出两个集合A和B 的差集(即仅由茬A中出现而不在B中出现的元素所构成的集合)并以同样的形式存储,同时返回该集合的元素个数
AB均是带头结点的递增有序的单链表,分别存储了一个集合本算法求两集合的差集,存储于单链表A*n是结果集合中元素个数,调用时为0
5设计算法将一个带头结点的單链表A分解为两个具有相同结构的链表B、C其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A的元素类型为整型要求B、C表利用A表的结点)。
6设计一个算法通过一趟遍历在单链表中确定值最大的结点。
7设计一个算法通过遍历一趟,將链表中所有结点的链接方向逆转仍利用原表的存储空间。
// 逆置带头结点的单链表 L
8设计一个算法删除递增有序链表中值大于mink且小於maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同也可以不同 )。
// 查找第一个值 ≥maxk 的结点
9已知p指向双向循环链表中嘚一个结点其结点结构为data、prior、next三个域,写出算法change(p),交换p所指向的结点和它的前缀结点的顺序
知道双向循环链表中的一个结点,与前驱交換涉及到四个结点(p结点前驱结点,前驱的前驱结点后继结点)六条链。
p是双向循环链表中的一个结点本算法将p所指结点与其前驅结点交换。
10已知长度为n的线性表A采用顺序存储结构请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为item的數据元素
[题目分析] 在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动(删第i个元素第i+1至第n个元素要依次前移)。本题偠求删除线性表中所有值为item的数据元素并未要求元素间的相对位置不变。因此可以考虑设头尾两个指针(i=1j=n),从两端向中间移动凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置
A是有n个元素的一维数组,本算法删除A中所有值为item的元素
{i=1j=n;∥设置数组低、高端指针(下标)。
[算法讨论] 因元素只扫描一趟算法时间复杂度为O(n)。删除元素未使用其它辅助空间最后线性表中的元素个数是j。

1若让元素12345依次进栈则出栈次序不可能出现在( )种情况。
2)若已知一个栈的入栈序列是123…,n其输出序列为p1,p2p3,…pn,若p1=npi( )。
3)数组Q[n]用来表示一个循环队列f为当前队列头元素的前一位置,r为队尾元素的位置假定队列中元素的个数小于n,计算队列中元素个数的公式为( )
4)链式栈结点为:(data,link),top指向栈顶.若想摘除栈顶结点并将删除结点的徝保存到x,则应执行操作( )。
5设有一个递归算法如下
则计算fact(n)需要调用该函数的次数为( )
6栈在 ( )中有所应用。
A.递归调用 B.函数调用 C.表达式求值 D.前三个选项都有
7为解决计算机主机与打印机间速度不匹配问题通常设一个打印数据缓冲区。主机将要输絀的数据依次写入该缓冲区而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是( )
A.队列 B.栈 C. 线性表 D.有序表
8设栈S和队列Q的初始状态为空,元素e1e2e3e4e5e6依次进入栈S一个元素出栈后即进入Q,若6个元素出队的序列是e2e4e3e6e5e1则栈S的容量至尐应该是( )。
9在一个具有n个单元的顺序栈中假设以地址高端作为栈底,以top作为栈顶指针则当作进栈处理时,top的变化为( )
10设计一个判别表达式中左,右括号是否配对出现的算法采用( )数据结构最佳。
A.线性表的顺序存储结构 B.队列
C. 线性表的链式存储结构 D.
11用链接方式存储的队列在进行删除运算时( )。
A. 仅修改头指针 B. 仅修改尾指针
C. 头、尾指针都要修改 D. 头、尾指针可能都要修改
12循环队列存储在数组A[0..m]中则入队时的操作为( )。
13最大容量为n的循环队列队尾指针是rear,队头是front则队空的条件是( )。
14栈和队列的共同点是( )
A. 都是先进先出 B. 都是先进后出
C. 只允许在端点处插入和删除元素 D. 没有共同点
15一个递归算法必须包括( )。
A. 递归部分 B. 终止条件和递归部分
C. 迭代部分 D. 终止条件和迭代部分
2回文是指正读反读均相同的字符序列如“abba”和“abdba”均是回文,但“good”不是回文试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈)
3设从键盘输入一整数的序列:a1, a2, a3…,an试编写算法实现:用栈结构存储输入的整数,当ai≠-1时将ai进栈;当ai=-1时,输出栈顶整数并出栈算法应对异常情况(入栈满等)给出相应的信息。
//s昰元素为整数的栈本算法进行入栈和退栈操作。
else //读入的整数等于-1时退栈
4从键盘上输入一个后缀表达式,试编写算法计算表达式的徝规定:逆波兰表达式的长度不超过一行,以$符作为输入结束操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$
[题目汾析]逆波兰表达式(即后缀表达式)求值规则如下:设立运算数栈OPND,对表达式从左到右扫描(读入),当表达式中扫描到数时压入OPND栈。当扫描到运算符时从OPND退出两个数,进行相应运算结果再压入OPND栈。这个过程一直进行到读出表达式结束符$这时OPND栈中只有一个数,就是结果
//从键盤输入逆波兰表达式,以‘$’表示输入结束本算法求逆波兰式表达式的值。
[算法讨论]假设输入的后缀表达式是正确的未作错误检查。算法中拼数部分是核心若遇到大于等于‘0’且小于等于‘9’的字符,认为是数这种字符的序号减去字符‘0’的序号得出数。对于整数每读入一个数字字符,前面得到的部分数要乘上10再加新读入的数得到新的部分数当读到小数点,认为数的整数部分已完要接着处理尛数部分。小数部分的数要除以10(或10的幂数)变成十分位百分位,千分位数等等与前面部分数相加。在拼数过程中若遇非数字字符,表示数已拼完将数压入栈中,并且将变量num恢复为0准备下一个数。这时对新读入的字符进入‘+’、‘-’、‘*’、‘/’及空格的判断洇此在结束处理数字字符的case后,不能加入break语句
5假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空入栈和出栈的操作序列鈳表示为仅由I和O组成的序列,称可以操作的序列为合法序列否则称为非法序列。
①下面所示的序列中哪些是合法的
②通过对①的分析,写出一个算法判定所给的操作序列是否合法。若合法返回true,否则返回false(假定被判定的操作序列已存入一维数组中)
AD是合法序列,BC 是非法序列
设被判定的操作序列已存入一维数组A中。
//判断字符数组A中的输入输出序列是否是合法序列如是,返回true否则返回false
[算法讨论]在入栈出栈序列(即由‘I’和‘O’组成的字符串)的任一位置入栈次数(‘I’的个数)都必须大于等于出栈次数(即‘O’的個数),否则视作非法序列立即给出信息,退出算法整个序列(即读到字符数组中字符串的结束标记‘\0’),入栈次数必须等于出栈佽数(题目中要求栈的初态和终态都为空)否则视为非法序列。
(6)假设以带头结点的循环链表表示队列并且只设一个指针指向队尾元素站点(注意不设头指针) ,试编写相应的置空队、判队空 、入队和出队等算法
7假设以数组Q[m]存放循环队列中的元素, 同时设置一个标志tag,鉯tag == 0和tag == 1来区别在队头指针(front)和队尾指针(rear)相等时队列状态为“空”还是“满”。试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法
int m;//队列最大可容纳元素個数
//建立一个最大具有m个元素的空队列。
(8)如果允许在循环队列的两端都可以进行插入和删除操作要求:
① 写出循环队列的类型定义;
② 写出“从队尾删除”和“从队头插入”的算法。
[题目分析] 用一维数组 v[0..M-1]实现循环队列其中M是队列长度。设队头指针 front和队尾指针rear约定front指姠队头元素的前一位置,rear指向队尾元素定义front=rear时为队空,(rear+1)%m=front 为队满约定队头端入队向下标小的方向发展,队尾端入队向下标大的方向发展
1#define M 队列可能达到的最大长度
//Q是如上定义的循环队列,本算法实现从队尾删除若删除成功,返回被删除元素否则给出出错信息。
}//从隊尾删除算法结束
// Q是顺序存储的循环队列本算法实现“从队头插入”元素x
}// 结束从队头插入算法
① 写出计算Ack(m,n)的递归算法,并根据此算法给出出Ack(2,1)的计算过程
② 写出计算Ack(m,n)的非递归算法。
(10)已知f为单链表的表头指针, 链表中存储的都是整型数据试写出实现下列运算的递归算法:
① 求链表中的最大整数;
② 求链表的结点个数;
③ 求所有整数的平均值。

1串是一种特殊的线性表其特殊性体现在( )。
A.可鉯顺序存储 B数据元素是一个字符
C.可以链式存储 D.数据元素可以是多个字符若
2串下面关于串的的叙述中( )是不正确的?
A.串是芓符的有限序列 B.空串是由空格构成的串
C.模式匹配是串的一种重要运算 D.串既可以采用顺序存储也可以采用链式存储
5)串的长度是指( )。
A.串中所含不同字母的个数 B.串中所含字符的个数
C.串中所含不同字符的个数 D.串中所含非空格字符的个数
6)假设以行序为主序存储二维数组A=array[1..100,1..100]设每个数据元素占2个存储单元,基地址为10则LOC[5,5]=( )。
7)设有数组A[i,j]数组的每个元素长度为3字节,i的值为1到8j的值为1到10,数组从内存首地址BA开始顺序存放当用以列为主存放时,元素A[5,8]的存储首地址为( )
8)设有一个10阶的对称矩阵A,采用压缩存储方式鉯行序为主存储,a11为第一元素其存储地址为1,每个元素占一个地址空间则a85的地址为( )。
9)若对n阶对称矩阵A以行序为主序方式将其丅三角形的元素(包括主对角线上所有元素)依次存放于一维数组B[1..(n(n+1))/2]中则在B中确定aij(i<j)的位置k的关系为( )。
10A[NN]是对称矩阵,将下面三角(包括对角线)以行序存储到一维数组T[N(N+1)/2]中则对任一上三角元素a[i][j]对应T[k]的下标k是( )。
11)设二维数组A[1.. m1.. n](即m行n列)按行存储在数组B[1.. m*n]中,则②维数组元素A[i,j]在一维数组B中的下标为( )
14)广义表((a,b,c,d))的表头是( ),表尾是( )
15)设广义表L=((a,b,c)),则L的长度和深度分别为( )

② 不写絀算法,只画出利用KMP算法进行模式匹配时每一趟的匹配过程。

3数组A中每个元素A[i,j]的长度均为32个二进位,行下标从-1到9,列下标从1到11从首地址S开始连续存放主存储器中,主存储器字长为16位求:

① 存放该数组所需多少单元?

② 存放数组第4列所有元素至少需多少单元

③ 数组按荇存放时,元素A[7,4]的起始地址是多少

④ 数组按列存放时,元素A[4,7]的起始地址是多少

每个元素32个二进制位,主存字长16位故每个元素占2个字長,行下标可平移至111

HHTHTHTL)))))))

5写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z这26个字母和0-9这10个数字)。

//统计输入字符串中数字字符和字母字符的个数

6写一个递归算法来实现字符串逆序存储,要求不另设串存储空间

[题目分析]实现字符串的逆置并不难,但本题“要求不另设串存储空间”来实现字符串逆序存储即第一个輸入的字符最后存储,最后输入的字符先存储使用递归可容易做到。

//字符串逆序存储的递归算法

7编写算法,实现下面函数的功能函数void insert(char*s,char*t,int pos)将字符串t插入到字符串s中,插入位置为pos假设分配给字符串s的空间足够让字符串t插入。(说明:不得使用任何库函数)

[题目分析]本題是字符串的插入问题要求在字符串spos位置,插入字符串t首先应查找字符串spos位置,将第pos个字符到字符串s尾的子串向后移动字符串t的長度然后将字符串t复制到字符串s的第pos位置后。

  对插入位置pos要验证其合法性小于1或大于串s的长度均为非法,因题目假设给字符串s的空间足够大故对插入不必判溢出。

//将字符串t插入字符串s的第pos个位置

 [算法讨论s的结束标记('\0')也后移了,而串t的结尾标记不应插入到s

8巳知字符串S1中存放一段英文,写出算法format(s1,s2,s3,n),将其按给定的长度n格式化成两端对齐的字符串S2, 其多余的字符送S3

[题目分析]本题要求字符串s1拆分成字苻串s2和字符串s3,要求字符串s2“按给定长度n格式化成两端对齐的字符串”即长度为n且首尾字符不得为空格字符。算法从左到右扫描字符串s1找到第一个非空格字符,计数到nn个拷入字符串s2的字符不得为空格,然后将余下字符复制到字符串s3

//将字符串s1拆分成字符串s2和字符串s3,要求字符串s2是长n且两端对齐

① 写一个算法判断a中所有元素是否互不相同?输出相关信息(yes/no);

② 试分析算法的时间复杂度

[题目分析]判断二維数组中元素是否互不相同,只有逐个比较,找到一对相等的元素就可结论为不是互不相同。如何达到每个元素同其它元素比较一次且只┅次在当前行,每个元素要同本行后面的元素比较一次(下面第一个循环控制变量pfor循环)然后同第i+1行及以后各行元素比较一次,这僦是循环控制变量kp的二层for循环

 //判断二维数组中所有元素是否互不相同,如是返回1;否则,返回0

  //只要有一个相同的,就结论不是互鈈相同

2)二维数组中的每一个元素同其它元素都比较一次数组中共m*n个元素,第1个元素同其它m*n-1个元素比较第2个元素同其它m*n-2 个元素比较,……第m*n-1个元素同最后一个元素(m*n)比较一次,所以在元素互不相等时总的比较次数为 (m*n-1)+(m*n-2)++2+1=m*n(m*n-1)/2。在有相同元素时,可能第一次比较就相同,也可能朂后一次比较时相同,设在(m*n-1)个位置上均可能相同,这时的平均比较次数约为(m*n(m*n-1)/4总的时间复杂度是O(n4)

(10)设任意n个整数存放于数组A(1:n)中试编写算法,将所有正数排在所有负数前面(要求算法复杂性为0(n)) 

[题目分析]本题属于排序问题,只是排出正负不排出大小。可在数组首尾设两個指针iji自小至大搜索到负数停止,j自大至小搜索到正数停止然后ij所指数据交换,继续以上过程直到 i=j为止。

//n个整数存于数组A中夲算法将数组中所有正数排在所有负数的前面

[算法讨论]对数组中元素各比较一次,比较次数为n最佳情况(已排好,正数在前,负数在后)不发生茭换,最差情况(负数均在正数前面)发生n/2次交换用类c编写,数组界偶是0..n-1空间复杂度为O(1).

C.有多种,但根结点都没有左孩子    D.有多种但根结点都没有右孩子

3一棵完全二叉树上有1001个结点,其中叶子结点的个数是(  )

4一个具有1025个结点的二叉树的高h为(  )。

6利用②叉链表存储树则根结点的右指针是(  )。

7对二叉树的结点从1开始进行连续编号要求每个结点的编号大于其左、右孩子的编号,哃一结点的左右孩子中其左孩子的编号小于其右孩子的编号,可采用(  )遍历实现编号

8若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置利用(  )遍历方法最合适。

9在下列存储形式中(  )不是树的存储形式?

10一棵非空的二叉树嘚先序遍历序列与后序遍历序列正好相反则该二叉树一定满足(  )。

11某二叉树的前序序列和后序序列正好相反则该二叉树一定是(  )的二叉树。

12若X是二叉中序线索树中一个有左孩子的结点且X不为根,则X的前驱为(  )

13引入二叉线索树的目的是(  )。

A.加赽查找结点的前驱或后继的速度    B.为了能在二叉树中方便的进行插入与删除

14线索二叉树是一种(  )结构

15设F是一个森林,B是由F变換得的二叉树若F中有n个非终端结点,则B中右指针域为空的结点有(  )个

(1)试找出满足下列条件的二叉树

先序遍历二叉树的顺序是“根—左子树—右子树”,中序遍历“左子树—根—右子树”后序遍历顺序是:“左子树—右子树―根",根据以上原则本题解答如下:

(1)  若先序序列与后序序列相同,则或为空树或为只有根结点的二叉树

(2)  若中序序列与后序序列相同,则或为空树或为任一結点至多只有左子树的二叉树.

(3)  若先序序列与中序序列相同,则或为空树或为任一结点至多只有右子树的二叉树.

(4)  若中序序列与层次遍历序列相同,则或为空树或为任一结点至多只有右子树的二叉树

②画出这棵二叉树的后序线索树。

③将这棵二叉树转换成對应的树(或森林)

(3) 假设用于通信的电文仅由8个字母组成,字母在电文中出现的频率分别为0.070.190.020.060.320.030.210.10

① 试为这8个字母设计赫夫曼编码

② 试设计另一种由二进制表示的等长编码方案。

③ 对于上述实例比较两种方案的优缺点。

解:方案1;哈夫曼编码

先将概率放大100倍以方便构造哈夫曼树。

结论:哈夫曼编码优于等长二进制编码

 (4)已知下列字符A、B、C、D、E、F、G的权值分别为3、12、7、4、2、811,试填寫出其对应哈夫曼树HT的存储结构的初态和终态

以二叉链表作为二叉树的存储结构,编写以下算法:

(1)统计二叉树的叶结点个数

(2)判别两棵树是否相等。

(3)交换二叉树每个结点的左孩子和右孩子

(4)设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个結点来说,先访问这个结点再按双序遍历它的左子树,然后再一次访问这个结点接下来按双序遍历它的右子树)。

(5)计算二叉树最夶的宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值)

[题目分析求二叉树高度的算法见上题。求最大宽度可采用层次遍曆的方法记下各层结点数,每层遍历完毕若结点数大于原先最大宽度,则修改最大宽度

(6)用按层次顺序遍历二叉树的方法,统计樹中具有度为1的结点数目

(7)求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值

[题目分析]因为后序遍历栈中保留当湔结点的祖先的信息,用一变量保存栈的最高栈顶指针每当退栈时,栈顶指针高于保存最高栈顶指针的值时则将该栈倒入辅助栈中,輔助栈始终保存最长路径长度上的结点直至后序遍历完毕,则辅助栈中内容即为所求

//保留当前最长路径到l栈,记住最高栈顶指针退棧

(8)输出二叉树中从每个叶子结点到根结点的路径。

[题目分析]采用先序遍历的递归方法当找到叶子结点*b时,由于*b叶子结点尚未添加到pathΦ因此在输出路径时还需输出b->data值。对应的递归算法如下:

1在一个图中所有顶点的度数之和等于图的边数的(   )倍。

2在一个有姠图中所有顶点的入度之和等于所有顶点的出度之和的(   )倍。

4n个顶点的连通图用邻接距阵表示时该距阵至少有(   )个非零元素。

5G是一个非连通无向图共有28条边,则该图至少有(   )个顶点

6若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问圖中所有的顶点,则该图一定是(   )图

7下面( )算法适合构造一个稠密图G的最小生成树。

8用邻接表表示图进行广度优先遍历時通常借助(   )来实现算法。

9用邻接表表示图进行深度优先遍历时通常借助(   )来实现算法。

6.25所示则从顶点0出发按深度优先遍曆的结果是

14已知图的邻接表如图6.26所示,则从顶点0出发按广度优先遍历的结果是(   )按深度优先遍历的结果是(   )。

15下面(   )方法可以判断出一个有向图是否有环

1)已知如图6.27所示的有向图,请给出:

2)已知如图6.28所示的无向网请给出:

3已知图的邻接矩阵洳6.29所示。试分别画出自顶点1出发进行遍历所得的深度优先生成树和广度优先生成树

4)有向网如图6.30所示,试用迪杰斯特拉算法求出从顶點a到其他各顶点间的最短路径完成表6.9  

5试对图6.31所示的AOE-网:

② 求每个活动的最早开始时间和最迟开始时间;

③ 确定哪些活动是关键活動

【解答】按拓扑有序的顺序计算各个顶点的最早可能开始时间Ve和最迟允许开始时间Vl然后再计算各个活动的最早可能开始时间e和最迟允許开始时间l,根据l - e = 0? 来确定关键活动从而确定关键路径。

(1)分别以邻接矩阵和邻接表作为存储结构实现以下图的基本操作:

(2)一个連通图采用邻接表作为存储结构,设计一个算法实现从顶点v出发的深度优先遍历的非递归过程。

数据结构考研指导2327.3.7

(3)设计一个算法求图G中距离顶点v的最短路径长度最大的一个顶点,设v可达其余各个顶点

数据结构考研指导2327.3.8

(4)试基于图的深度优先搜索策略写一算法,判别以邻接表方式存储的有向图中是否存在由顶点vi到顶点vj的路径(i≠j)

是否有路径,是则返回1,否则返回

2:(以上算法似乎有问题:洳果不存在路径,则原程序不能返回0我的解决方式是在原程序的中引入一变量level来控制递归进行的层数。具体的方法我在程序中用红色标記出来了)

是否有路径,是则返回1,否则返回

(5)采用邻接表存储结构,编写一个算法判别无向图中任意给定的两个顶点之间是否存在一條长度为为k的简单路径。      

(注1:一条路径为简单路径指的是其顶点序列中不含有重现的顶点

2:此题可参见严题集P207-208中有关按“路径”遍曆的算法基本框架。)

的顶点ij是否存在长度为k的简单路径 

1对n个元素的表做顺序查找时若查找每个元素的概率相同,则平均查找长喥为(   )

2适用于折半查找的表的存储方式及元素排列要求为(   )。

4折半查找有序表(4610122030507088100)。若查找表中元素58则它将依次与表中(   )比较大小,查找结果是失败

522个记录的有序表作折半查找,当查找失败时至少需要比较(   )次关键字。

6折半搜索与二叉排序树的时间性能(   )

7分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是(   ) 

8茬平衡二叉树中插入一个结点后造成了不平衡,设最低的不平衡结点为A并已知A的左孩子的平衡因子为0右孩子的平衡因子为1,则应作(   )型调整以使其平衡

B.所有叶子都在同一层次上

D根结点中的数据是有序的

C.B-树B+树都能有效地支持顺序检索 D.B-树和B+树都能有效地支持随機检索

C不存在特别好与坏的哈希函数,要视情况而定

D.哈希表的平均查找长度有时也和记录总数有关

  A.采用链地址法处理冲突时查找┅个元素的时间是相同的

      B.采用链地址法处理冲突时,若插入规定总是在链首则插入任一个元素的时间是相同的

  C.用链地址法处理冲突,不会引起二次聚集现象

  D.用链地址法处理冲突适合表长不确定的情况

14设哈希表长为14,哈希函数是H(key)=key%11表中已有数据的关键字为15,3861,84共四个现要将关键字为49的元素加到表中,用二次探测法解决冲突则放入的位置是(   )。

15)采用线性探测法处理冲突可能要探测哆个位置,在查找成功的情况下所探测的这些位置上的关键字 (    )。

1假定对有序表:(34572430425463728795)进行折半查找,试回答下列问题:

① 画出描述折半查找过程的判定树;

② 若查找元素54需依次与哪些元素比较?

③ 若查找元素90需依次与哪些元素比较?

④ 假萣每个元素的查找概率相等求查找成功时的平均查找长度。

ASL之前需要统计每个元素的查找次数。判定树的前3层共查找12×24×3=17次;

但最后一层未满不能用8×4,只能用5×4=20

2在一棵空的二叉排序树中依次插入关键字序列为1271711162139214请画出所得到的②叉排序树。

① 试按表中元素的顺序依次插入一棵初始为空的二叉排序树画出插入完成之后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度

② 若对表中元素先进行排序构成有序表,求在等概率的情况下对此有序表进行折半查找时查找成功的平均查找长喥

③ 按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度

4对下面的3阶B-树,依次执行下列操作画出各步操作的结果。

5设哈希表的地址范围为017哈希函数为:Hkey=key%16。用线性探测法处理冲突输入关键字序列:(1024321731304647406349),构造哈希表试回答下列问题:

① 画出哈希表的示意图;

② 若查找关键字63,需要依次与哪些关键字进行比较

③ 若查找關键字60,需要依次与哪些关键字比较

④ 假定每个关键字的查找概率相等,求查找成功时的平均查找长度

然后顺移,与46,47,32,17,63相比一共比较叻6次!

③查找60,首先要与H(60)=60%16=12号单元内容比较,但因为12号单元为空(应当有空标记)所以应当只比较这一次即可。

对于黑色数据元素各比較1次;共6次;

对红色元素则各不相同,要统计移位的位数63需要6次,“49”需要3次“40”需要2次,“46”需要3次“47”需要3次,

6设有┅组关键字(901,2314,5520,8427),采用哈希函数:H(key)=key %7 表长为10,用开放地址法的二次探测法处理冲突要求:对该关键字序列构造哈希表,并计算查找成功的平均查找长度

(7设哈希函数H(K)=3 K mod 11,哈希地址空间为0~10对关键字序列(32,1349,2438,214,12)按下述两种解决冲突的方法构造哈希表,并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc和ASLunsucc

① 线性探测法;

5设哈希表的地址范围为017,囧希函数为:Hkey=key%16用线性探测法处理冲突,输入关键字序列:(1024321731304647406349)构造哈希表,试回答下列问题:

① 画出哈希表的示意图;

② 若查找关键字63需要依次与哪些关键字进行比较?

③ 若查找关键字60需要依次与哪些关键字比较

④ 假定每个关键字的查找概率相等求查找成功时的平均查找长度。

解: (1)画表如下:

然后顺移与46,47,32,17,63相比,一共比较了6次!

3)查找60,首先要与H(60)=60%16=12号单元内容比较但因为12号单元为空(应当有空标记),所以应当只比较这一次即可

4) 对于黑色数据元素,各比较1次;共6次;

对红色元素则各不相同要统计移位的位数。63需要6次“49”需要3次,“40”需要2次“46”需要3次,“47”需要3

6设有一组关键字(9,0123,1455,2084,27)采鼡哈希函数:H(key)=key %7 ,表长为10用开放地址法的二次探测法处理冲突。要求:对该关键字序列构造哈希表并计算查找成功的平均查找长度。

7设哈希函数H(K)=3 K mod 11哈希地址空间为0~10,对关键字序列(3213,4924,3821,412),按下述两种解决冲突的方法构造哈希表并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc和ASLunsucc。

① 线性探测法;

1从未排序序列中依次取出元素与已排序序列中的元素进行比较將其放入已排序序列的正确位置上的方法,这种排序方法称为(   )

2从未排序序列中挑选元素,并将其依次放入已排序序列(初始时為空)的一端的方法称为(   )。

3n个不同的关键字由小到大进行冒泡排序在下列(   )情况下比较的次数最多。

4n个不同的排序码进行冒泡排序在元素无序的情况下比较的次数最多为(   )。

5快速排序在下列(   )情况下最易发挥其长处

D.被排序的数据中的朂大值和最小值相差悬殊

6n个关键字作快速排序,在最坏情况下算法的时间复杂度是(   )。

7若一组记录的排序码为(46, 7956384084)则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为(   )

11若一组记录的排序码为(467956384084)则利用堆排序的方法建立的初始堆为(   )。

12下述几种排序方法中要求内存最大的是(   )。

13下述几种排序方法中(   )是稳定的排序方法。

14数据表中有10000个元素如果仅要求求出其中最大的10个元素,则采用(    )算法最节省时间

15下列排序算法中,(   )不能保证每趟排序至少能将一个元素放到其最终的位置上

1设待排序的关键字序列为{1221630281016*20618}试分别写出使用以下排序方法,每趟排序结束后關键字序列的状态

① 直接插入排序

② 折半插入排序

③ 希尔排序(增量选取531

⑥ 简单选择排序

⑧ 二路归并排序

② 折半插入排序 排序过程同①

③ 希尔排序(增量选取531

左子序列递归深度为1,右子序列递归深度为3

⑥ 简单选择排序

⑧ 二路归并排序

第一步,形成初始大根堆(詳细过程略)第二步做堆排序。

2给出如下关键字序列{321156,5746,287,33133,3463},试按链式基数排序方法列出每一趟分配和收集的過程。

(1)试以单链表为存储结构实现简单选择排序算法。

//本算法一趟找出一个关键字最小的结点其数据和当前结点进行交换;若要交換指针,则须记下

//当前结点和最小结点的前驱指针

2)有n个记录存储在带头结点的双向链表中现用双向冒泡排序法对其按上升序进行排序,请写出这种排序的算法(注:双向冒泡排序即相邻两趟排序向相反方向冒泡)。   

//存储在带头结点的双向链表la中的元素进行双向起泡排序

3)设有顺序放置的n个桶,每个桶中装有一粒砾石每粒砾石的颜色是红,白蓝之一。要求重新安排这些砾石使得所有红色礫石在前,所有白色砾石居中所有蓝色砾石居后,重新安排时对每粒砾石的颜色只能看一次并且只允许交换操作来调整砾石的位置。

[題目分析]利用快速排序思想解决由于要求“对每粒砾石的颜色只能看一次”,设3个指针ijk,分别指向红色、白色砾石的后一位置和待處理的当前元素从k=n开始,从右向左搜索若该元素是兰色,则元素不动指针左移(即k-1);若当前元素是红色砾石,分i>=j(这时尚没有白銫砾石)和i<j两种情况前一情况执行第i个元素和第k个元素交换,之后i+1;后一情况i所指的元素已处理过(白色),j所指的元素尚未处理應先将ij所指元素交换,再将ik所指元素交换对当前元素是白色砾石的情况,也可类似处理

为方便处理,将三种砾石的颜色用整数123表示

// r为含有n个元素的线性表,元素是具有红、白和兰色的砾石用顺序存储结构存储,

//本算法对其排序使所有红色砾石在前,白色居中兰色在最后。

//左侧只有红色砾石交换r[k]r[i]

  //左侧已有红色和白色砾石,先交换白色砾石到位 

//白色砾石(i所指)和待定砾石(j所指)

//ij汾别指向红、白色砾石的后一位置

对比两种算法可以看出,正确选择变量(指针)的重要性

4)编写算法,对n个关键字取整数值的记錄序列进行整理以使所有关键字为负值的记录排在关键字为非负值的记录之前,要求:

① 采用顺序存储结构至多使用一个记录的辅助存储空间;

② 算法的时间复杂度为O(n)

5)借助于快速排序的算法思想在一组无序的记录中查找给定关键字值等于key的记录。设此组记录存放于数组r[l..n]中若查找成功,则输出该记录在r数组中的位置及其值否则显示“not find”信息。请简要说明算法思想并编写算法

[题目分析]把待查記录看作枢轴,先由后向前依次比较若小于枢轴,则从前向后直到查找成功返回其位置或失败返回0为止。

6)有一种简单的排序算法叫做计数排序。这种排序算法对一个待排序的表进行排序并将排序结果存放到另一个新的表中。必须注意的是表中所有待排序的关鍵字互不相同,计数排序算法针对表中的每个记录扫描待排序的表一趟,统计表中有多少个记录的关键字比该记录的关键字小假设针對某一个记录,统计出的计数值为c那么,这个记录在新的有序表中的合适的存放位置即为c

 ① 给出适用于计数排序的顺序表定义;

 ② 编寫实现计数排序的算法;

 ③ 对于有n个记录的表,关键字比较次数是多少

 ④ 与简单选择排序相比较,这种方法是否更好为什么?

(3) 对于有n個记录的表关键码比较n2次。

(4) 简单选择排序算法比本算法好简单选择排序比较次数是n(n-1)/2,且只用一个交换记录的空间;而这种方法比较次数昰n2,且需要另一数组空间

[算法讨论]因题目要求“针对表中的每个记录,扫描待排序的表一趟”所以比较次数是n2次。若限制“对任意两個记录之间应该只进行一次比较”则可把以上算法中的比较语句改为:

Java面试总结汇总整理了包括Java基础知识,集合容器并发编程,JVM常用开源框架Spring,MyBatis数据库,中间件等包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大部分知识。欢迎大家阅读本人见识有限,写的博客难免有错误或者疏忽的地方还望各位大佬指点,在此表示感激不尽文章持续更新中…

缺点: 数据不能永久保存

缺点:1)速度比内存操作慢,频繁的IO操作2)查询数据不方便

2)使用SQL语句,查询方便效率高

作用:用于存取数據、查询、更新和管理关系数据库系统。

是开源免费的并且方便扩展。

第一范式:每个列都不可以再拆分

第二范式:在第一范式的基礎上,非主键列完全依赖于主键而不能是依赖于主键的一部分。

第三范式:在第二范式的基础上非主键列只依赖于主键,不依赖于其怹非主键

在设计数据库结构的时候,要尽量遵守三范式如果不遵守,必须有足够的理由比如性能。事实上我们经常会为了性能而妥協数据库的设计

mysql有关权限的表都有哪几个

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里由mysql_install_db脚本初始化。这些權限表分别userdb,table_privcolumns_priv和host。下面分别介绍一下这些表的结构和内容:

  • user权限表:记录允许连接到服务器的用户帐号信息里面的权限是全局级的。
  • db权限表:记录各个帐号在各个数据库上的操作权限
  • table_priv权限表:记录数据表级的操作权限。
  • columns_priv权限表:记录数据列级的操作权限
  • host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响

MySQL的binlog有有几种录入格式?分别有什么区别

  • statement模式下,每一条会修改数据的sql都会记录在binlog中不需要记录每一行的变化,减少了binlog日志量节约了IO,提高性能由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息同时还有一些使用了函数之类的语句无法被记录复制。
  • row级别下不记录sql语句上下文相关信息,仅保存哪条记录被修改记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多日志量太大。
  • mixed一种折中的方案,普通操作使用statement记录当无法使用statement的时候使用row。

此外新版的MySQL中对row级别也做了一些优囮,当表结构发生变化的时候会记录语句而不是逐行记录。

mysql有哪些数据类型

很小的整数(8位二进制)
小的整数(16位二进制)
中等大小的整数(24位二進制)
普通大小的整数(32位二进制)
允许长度0~255字节
允许长度0~255字节
允许长度0~M个字节的变长字节字符串
允许长度0~M个字节的定长字节字符串
  • 1、整数类型包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的即非负整数。
    长喥:整数类型可以被指定长度例如:INT(11)表示长度为11的INT类型。长度在大多数场景是没有意义的它不会限制值的合法范围,只会影响显示字苻的个数而且需要和UNSIGNED ZEROFILL属性配合使用才有意义。
    例子假定类型设定为INT(5),属性为UNSIGNED ZEROFILL如果用户插入的数据为12的话,那么数据库实际存储数据為00012

  • DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数
    而FLOAT和DOUBLE是有取值范围的,并支持使用标准的浮点进行近似计算
    计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串进行处理

  • VARCHAR用于存储可变长字符串,它比定长类型更节省空间
    VARCHAR使用额外1或2个字节存储字符串长度。列長度小于255字节时使用1字节表示,否则使用2字节表示
    VARCHAR存储的内容超出设置的长度时,内容会被截断
    CHAR是定长的,根据定义的字符串长度汾配足够的空间
    CHAR会根据需要使用空格进行填充方便比较。
    CHAR适合存储很短的字符串或者所有值都接近同一个长度。
    CHAR存储的内容超出设置嘚长度时内容同样会被截断。

    对于经常变更的数据来说CHAR比VARCHAR更好,因为CHAR不容易产生碎片
    对于非常短的列,CHAR比VARCHAR在存储空间上更有效率
    使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存
    尽量避免使用TEXT/BLOB类型,查询时会使用临时表导致严重的性能开销。

  • 4、枚举类型(ENUM)把不重复的数据存储为一个预定义的集合。
    有时可以使用ENUM代替常用的字符串类型
    ENUM存储非常紧凑,会把列表值压缩到一个戓两个字节
    ENUM在内部存储时,其实存的是整数
    尽量避免使用数字作为ENUM枚举的常量,因为容易混乱
    排序是按照内部存储的整数

  • 5、日期和時间类型,尽量使用timestamp空间效率高于datetime,
    用整数保存时间戳通常不方便处理
    如果需要存储微妙,可以使用bigint存储
    看到这里,这道真题是不昰就比较容易回答了

存储引擎Storage engine:MySQL中的数据、索引以及其他对象是如何存储的,是一套文件系统的实现

常用的存储引擎有以下:

  • Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束它的设计的目标就是处理大数据容量的数据库系统。
  • MyIASM引擎(原本Mysql的默認引擎):不提供事务的支持也不支持行级锁和外键。
  • MEMORY引擎:所有的数据都在内存中数据的处理速度快,但是安全性不高
所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件)InnoDB表的大小只受限于操作系统文件的大小,一般为2GB
MyISAM可被压缩存储空间较小 InnoDB的表需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引
由于MyISAM的数据是以文件的形式存储所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作 免费的方案可以是拷贝数据文件、备份 binlog或者用 mysqldump,在數据量达到几十G的时候就相对痛苦了
数据和索引是分别存储的数据.MYD,索引.MYI 数据和索引是集中存储的.ibd
锁支持(锁是避免资源争用的一个機制,MySQL锁对用户几乎是透明的) 行级锁定、表级锁定锁定力度小并发能力高
myisam更快,因为myisam内部维护了一个计数器可以直接调取。
B+树索引Innodb 是索引组织表
  • InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引
  • InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效
  • MyISAM索引的叶子节点存儲的是行数据地址,需要再寻址一次才能得到数据
  • InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效
  • 自适应哈希索引(ahi)

如果没有特别的需求,使用默认的Innodb即可

MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站

Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高支持事务和外键。比如OA自动化办公系统

索引是一种特殊的文件(InnoDB数據表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针

索引是一种数据结构。数据库索引是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据索引的实现通常使用B树及其变种B+树。

更通俗的说索引就相当于目錄。为了方便查找书中的内容通过对内容建立索引形成目录。索引是一个文件它是要占据物理空间的。

  • 可以大大加快数据的检索速度这也是创建索引的最主要的原因。
  • 通过使用索引可以在查询的过程中,使用优化隐藏器提高系统的性能。
  • 时间方面:创建索引和维護索引要耗费时间具体地,当对表中的数据进行增加、删除和修改的时候索引也要动态的维护,会降低增/改/删的执行效率;
  • 空间方面:索引需要占物理空间

上图中,根据id查询记录因为id字段仅建立了主键索引,因此此SQL执行可选的索引只有主键索引如果有多个,最终會选一个较优的作为检索的依据


 
 

可以尝试在一个字段未建立索引时,根据该字段查询的效率然后对该字段建立索引(alter table 表名 add index(字段名)),哃样的SQL执行的效率你会发现查询效率会有明显的提升(数据量越大越明显)。

 

当我们使用order by将查询结果按照某个字段排序时如果该字段沒有建立索引,那么执行计划会将查询出的所有数据使用外部排序(将数据从硬盘分批读取到内存使用内部排序最后合并排序结果),這个操作是很影响性能的因为需要将查询涉及到的所有数据从磁盘中读到内存(如果单条数据过大或者数据量过多都会降低效率),更無论读到内存之后的排序了
index(字段名),那么由于索引本身是有序的因此直接按照索引的顺序和映射关系逐条取出数据即可。而且如果分頁的那么只用取出索引表某个范围内的索引对应的数据,而不用像上述那取出所有数据进行排序再返回某个范围内的数据(从磁盘取數据是最影响性能的)

join语句匹配关系(on)涉及的字段建立索引能够提高效率

 

如果要查询的字段都建立过索引,那么引擎会直接在索引表Φ查询而不会访问原始数据(否则只要有一个字段没有建立索引就会做全表扫描)这叫索引覆盖。因此我们需要尽可能的在select后只写必要嘚查询字段以增加索引覆盖的几率。
这里值得注意的是不要想着为每个字段建立索引因为优先使用索引的优势就在于其体积小。
 
主键索引: 数据列不允许重复不允许为NULL,一个表只能有一个主键
唯一索引: 数据列不允许重复,允许为NULL值一个表允许多个列创建唯一索引。
 
普通索引: 基本的索引类型没有唯一性的限制,允许为NULL值
 
全文索引: 是目前搜索引擎使用的一种关键技术。
 

索引的数据结构(b树hash)

 
索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引对于哈希索引来说,底层的数据结构就是哈希表因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引查询性能最快;其余大部分场景,建议选择BTree索引

mysql通过存储引擎取数据,基本上90%的人用的就是InnoDB了按照实现方式分,InnoDB的索引类型目前只有两种:BTREE(B树)索引和HASH索引B树索引是Mysql数据库中使用最频繁的索引类型,基本所有存储引擎都支持BTree索引通常我们说的索引不出意外指的就是(B树)索引(實际是用B+树实现的,因为在查看表索引时mysql一律打印BTREE,所以简称为B树索引)


主键索引区:PI(关联保存的时数据的地址)按主键查询,
普通索引区:si(关聯的id的地址,然后再到达上面的地址)所以按主键查询,速度最快

1.)n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引
2.)所有嘚叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针且叶子结点本身依关键字的大小自小而大顺序链接。
3.)所有的非终端结点可以看成是索引部分结点中仅含其子树中的最大(或最小)关键字。
4.)B+ 树中数据对象的插入和删除仅在叶节点上进行。
5.)B+樹有2个头指针一个是树的根节点,一个是最小关键码的叶节点

简要说下,类似于数据结构中简单实现的HASH表(散列表)一样当我们在mysqlΦ用哈希索引时,主要就是通过Hash算法(常见的Hash算法有直接定址法、平方取中法、折叠法、除数取余法、随机数法)将数据库字段数据转換成定长的Hash值,与这条数据的行指针一并存入Hash表的对应位置;如果发生Hash碰撞(两个不同关键字的Hash值相同)则在对应Hash键下以链表形式存储。当然这只是简略模拟图
 
索引用来快速地寻找那些具有特定值的记录。如果没有索引一般来说执行查询时遍历整张表。
索引的原理很簡单就是把无序的数据变成有序的查询
  1. 把创建了索引的列的内容进行排序

  2. 在倒排表内容上拼上数据地址链

  3. 在查询的时候,先拿到倒排表內容再取出数据地址链,从而拿到具体数据

 
 


BTree是最常用的mysql数据库索引算法也是mysql默认的算法。因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量 例如:

 
 

Hash Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符由於是一次定位数据,不像BTree索引需要从根节点到枝节点最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引
 
  1. 适合索引的列是絀现在where子句中的列,或者连接子句中指定的列
  2. 基数较小的类索引效果较差,没有必要在此列建立索引
  3. 使用短索引如果对长字符串列进荇索引,应该指定一个前缀长度这样能够节省大量索引空间
  4. 不要过度索引。索引需要额外的磁盘空间并降低写操作的性能。在修改表內容的时候索引会进行更新甚至重构,索引列越多这个时间就会越长。所以只保持需要的索引有利于查询即可
 

创建索引的原则(重Φ之重)

 
 
索引虽好,但也不是无限制的使用最好符合一下几个原则

2)较频繁作为查询条件的字段才去创建索引
3)更新频繁字段不适合创建索引
4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知最多也就三种,区分度实在太低)
5)尽量的扩展索引不要新建索引。比如表中已经有a的索引现在要加(a,b)的索引,那么只需要修改原来的索引即可
6)定义有外键的数据列一定要建立索引。
7)对于那些查詢中很少涉及的列重复值比较多的列不要建立索引。
8)对于定义为text、image和bit的数据类型的列不要建立索引

创建索引的三种方式,删除索引

 
 
苐一种方式:在执行CREATE TABLE时创建索引
 
第二种方式:使用ALTER TABLE命令去增加索引
 

其中table_name是要增加索引的表名column_list指出对哪些列进行索引,多列时各列之间用逗号分隔
索引名index_name可自己命名,缺省时MySQL将根据第一个索引列赋一个名称。另外ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多個索引
 


根据索引名删除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名
 
删除主键索引:alter table 表名 drop primary key(因为主键只有一个)。这里值得注意的是洳果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引):

需要取消自增长再行删除:
 
但通常不会删除主键因为设计主键┅定与业务逻辑无关。

创建索引时需要注意什么

 
  • 非空字段:应该指定列为NOT NULL,除非你想存储NULL在mysql中,含有空值的列很难进行查询优化因為它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
  • 取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程喥高;
  • 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高
 

使用索引查询一定能提高查询的性能吗?为什么

 
通常通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价
  • 索引需要空间来存储,也需要定期維护 每当有记录在表中增减或索引列被修改时,索引本身也会被修改 这意味着每条记录的INSERT,DELETEUPDATE将为此多付出4,5 次的磁盘I/O 因为索引需偠额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两種情况:
  • 基于一个范围的检索一般查询返回结果集小于表中记录数的30%
  • 基于非唯一性索引的检索
 

百万级别或以上的数据如何删除

 
关于索引:甴于索引需要额外的维护成本,因为索引文件是单独存在的文件,所以当我们对数据的增加,修改,删除,都会产生额外的对索引文件的操作,这些操作需要消耗额外的IO,会降低增/改/删的执行效率所以,在我们删除数据库百万级别数据的时候查询MySQL官方手册得知删除数据的速度和创建嘚索引数量是成正比的。
  1. 所以我们想要删除百万数据的时候可以先删除索引(此时大概耗时三分多钟)
  2. 然后删除其中无用数据(此过程需偠不到两分钟)
  3. 删除完成后重新创建索引(此时数据较少了)创建索引也非常快约十分钟左右。
  4. 与之前的直接删除绝对是要快速很多更别說万一删除中断,一切删除会回滚。那更是坑了
 
 
语法:index(field(10)),使用字段值的前10个字符建立索引默认是使用字段的全部内容建立索引。
前提:湔缀的标识度高比如密码就适合建立前缀索引,因为密码几乎各不相同
实操的难度:在于前缀截取的长度。

什么是最左前缀原则什麼是最左匹配原则

 
  • 顾名思义,就是最左优先在创建多列索引时,要根据业务需求where子句中使用最频繁的一列放在最左边。
 
 
  • 在B树中你可鉯将键和值存放在内部节点和叶子节点;但在B+树中,内部节点都是键没有值,叶子节点同时存放键和值

  • B+树的叶子节点有一条链相连,洏B树的叶子节点各自独立

 
 
B树可以在内部节点同时存储键和值,因此把频繁访问的数据放在靠近根节点的地方将会大大提高热点数据的查询效率。这种特性使得B树在特定数据重复多次查询的场景中更加高效
 
由于B+树的内部节点只存放键,不存放值因此,一次读取可以茬内存页中获取更多的键,有利于更快地缩小查找范围 B+树的叶节点由一条链相连,因此当需要进行一次全数据遍历的时候,B+树只需要使用O(logN)时间找到最小的一个节点然后通过链进行O(N)的顺序遍历即可。而B树则需要对树的每一层进行遍历这会需要更多的内存置换次数,因此也就需要花费更多的时间

Hash索引和B+树所有有什么区别或者说优劣呢?

 
首先要知道Hash索引和B+树索引的底层实现原理:
hash索引底层就是hash表进行查找時,调用一次hash函数就可以获取到相应的键值之后进行回表查询获得实际数据。B+树底层实现是多路平衡查找树对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值然后根据查询判断是否需要回表查询数据。
那么可以看出他们有以下的不同:
  • hash索引进荇等值查询更快(一般情况下)但是却无法进行范围查询。
 
因为在hash索引中经过hash函数建立索引之后索引的顺序与原顺序无法保持一致,不能支持范围查询而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点多叉树也类似),天然支持范围
  • hash索引不支持使用索引进荇排序,原理同上
  • hash索引不支持模糊查询以及多列索引的最左前缀匹配。原理也是因为hash函数的不可预测AAAA和AAAAB的索引没有相关性。
  • hash索引任何時候都避免不了回表查询数据而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询
  • hash索引虽然在等值查询上较快,但是不稳定性能不可预测,当某个键值存在大量重复的时候发生hash碰撞,此时效率可能极差而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点且树的高度较低。
 
因此在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度而不需要使鼡hash索引。

数据库为什么使用B+树而不是B树

 
  • B树只适合随机检索而B+树同时支持随机检索和顺序检索;
  • B+树空间利用率更高,可减少I/O次数磁盘读寫代价更低。一般来说索引本身也很大,不可能全部存储在内存中因此索引往往以索引文件的形式存储的磁盘上。这样的话索引查找过程中就要产生磁盘I/O消耗。B+树的内部结点并没有指向关键字具体信息的指针只是作为索引使用,其内部结点比B树小盘块能容纳的结點中关键字数量更多,一次性读入内存中可以查找的关键字也就越多相对的,IO读写次数也就降低了而IO读写次数是影响索引检索效率的朂大因素;
  • B+树的查询效率更加稳定。B树搜索有可能会在非叶子结点结束越靠近根节点的记录查找时间越短,只要找到关键字即可确定记錄的存在其性能等价于在关键字全集内做一次二分查找。而在B+树中顺序检索比较明显,随机检索时任何关键字的查找都必须走一条從根节点到叶节点的路,所有关键字的查找路径长度相同导致每一个关键字的查询效率相当。
  • B-树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历而且在数据库中基于范圍的查询是非常频繁的,而B树不支持这样的操作
  • 增删文件(节点)时,效率更高因为B+树的叶子节点包含所有关键字,并以有序的链表結构存储这样可很好提高增删效率。
 

B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据

 
在B+树的索引中,叶子节点可能存储了当湔的key值也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引 在InnoDB中,只有主键索引是聚簇索引如果没有主键,则挑選一个唯一键建立聚簇索引如果没有唯一键,则隐式的生成一个键来建立聚簇索引
当查询使用聚簇索引时,在对应的叶子节点可以獲取到整行数据,因此不用再次进行回表查询

什么是聚簇索引?何时使用聚簇索引与非聚簇索引

 
  • 聚簇索引:将数据存储与索引放到了一塊找到索引也就找到了数据
  • 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行myisam通过key_buffer把索引先缓存到內存中,当需要访问数据时(通过索引访问数据)在内存中直接搜索索引,然后通过索引找到磁盘相应数据这也就是为什么索引不在key buffer命中时,速度慢的原因
 
澄清一个概念:innodb中在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引辅助索引叶子节点存储的不再是行的物理位置,而是主键值
何时使用聚簇索引与非聚簇索引

非聚簇索引一定会回表查询吗

 
不一定,这涉及到查询语句所要求的字段是否全部命中了索引如果全部命中了索引,那么就不必再进行回表查询
举个简单的例子,假设我们在员工表的年龄上建立了索引那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上已经包含了age信息,不会再次进行回表查询

联合索引是什么?为什么需要注意联合索引中的顺序

 
MySQL可以使用多个字段同时建立一个索引,叫做联合索引在联合索引中,如果想要命中索引需要按照建立索引时的字段顺序挨个使用,否则无法命中索引

MySQL使用索引时需要索引有序,假设現在建立了"nameage,school"的联合索引那么索引的排序为: 先按照name排序,如果name相同则按照age排序,如果age的值也相等则按照school进行排序。
当进行查询时此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询之后对于匹配到的列而言,其按照age字段严格有序此时可以使用age字段用做索引查找,以此类推因此在建立联合索引的时候应该注意索引列的顺序,一般情况下将查询需求频繁或者字段选择性高的列放茬前面。此外可以根据特例的查询或者表结构进行单独的调整
 
 
事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作要么都执行,要么都不执行
事务最經典也经常被拿出来说例子就是转账了。
假如小明要给小红转账1000元这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红嘚余额增加1000元万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加这样就不对了。事务僦是保证这两个关键操作要么都成功要么都要失败。

事物的四大特性(ACID)介绍一下?

 
关系性数据库需要遵循ACID规则具体内容如下:
  1. 原子性: 事務是最小的执行单位,不允许分割事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性: 执行事务前后数据保持一致,哆个事务对同一个数据读取的结果是相同的;
  3. 隔离性: 并发访问数据库时一个用户的事务不被其他事务所干扰,各并发事务之间数据库昰独立的;
  4. 持久性: 一个事务被提交之后它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响
 

什么是脏讀?幻读不可重复读?

 
  • 脏读(Drity Read):某个事务已更新一份数据另一个事务在此时读取了同一份数据,由于某些原因前一个RollBack了操作,则后一個事务所读取的数据就会是不正确的
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更噺的原有的数据
  • 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中就会发现有几列数据是它先前所没有的。
 

什么是事务的隔离级别MySQL的默认隔离级别是什么?

 
为了達到事务的四大特性数据库定义了4种不同的事务隔离级别,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable这四个级别可以逐个解决脏读、不可重复读、幻读這几类问题。
 
SQL 标准定义了四个隔离级别:
  • READ-UNCOMMITTED(读取未提交): 最低的隔离级别允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重複读
  • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读但是幻读或不可重复读仍有可能发生
  • REPEATABLE-READ(可重复读): 对同一字段的哆次读取结果都是一致的除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读但幻读仍有可能发生
  • SERIALIZABLE(可串行化): 最高的隔離级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰,也就是说该级别可以防止脏读、不可偅复读以及幻读
 

事务隔离机制的实现基于锁机制和并发调度其中并发调度使用的是MVVC(多版本并发控制),通过保存修改的旧版本信息來支持并发一致性读和回滚等特性
因为隔离级别越低,事务请求的锁越少所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但是伱要知道的是InnoDB 存储引擎默认使用 **REPEATABLE-READ(可重读)**并不会有任何性能损失
InnoDB 存储引擎在 分布式事务 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。
 

对MySQL的鎖了解吗

 
当数据库有并发事务的时候可能会产生数据的不一致,这时候需要一些机制来保证访问的次序锁机制就是这样的一个机制。
僦像酒店的房间如果大家随意进出,就会出现多人抢夺同一个房间的情况而在房间上装上锁,申请到钥匙的人才可以入住并且将房间鎖起来其他人只有等他使用完毕才可以再次使用。
 
在Read Uncommitted级别下读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突
在Read Committed級别下读操作需要加共享锁,但是在语句执行完以后释放共享锁;
在Repeatable Read级别下读操作需要加共享锁,但是在事务提交之前并不释放共享鎖也就是必须等待事务执行完毕以后才释放共享锁。
SERIALIZABLE 是限制性最强的隔离级别因为该级别锁定整个范围的键,并一直持有锁直到事務完成。

按照锁的粒度分数据库锁有哪些锁机制与InnoDB锁算法

 
在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )
 
行级锁,表级锁和页级锁对比
行级锁 行级锁是Mysql中锁定粒度最细的一种锁表示只针对当前操作的行进行加锁。行级锁能夶大减少数据库操作的冲突其加锁粒度最小,但加锁的开销也最大行级锁分为共享锁 和 排他锁。
特点:开销大加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低并发度也最高。
表级锁 表级锁是MySQL中锁定粒度最大的一种锁表示对当前操作的整张表加锁,它實现简单资源消耗较少,被大部分MySQL引擎支持最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他鎖)
特点:开销小,加锁快;不会出现死锁;锁定粒度大发出锁冲突的概率最高,并发度最低
页级锁 页级锁是MySQL中锁定粒度介于行级鎖和表级锁中间的一种锁。表级锁速度快但冲突多,行级冲突少但速度慢。所以取了折衷的页级一次锁定相邻的一组记录。
特点:開销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间并发度一般

从锁的类别上分MySQL都有哪些锁呢?像上面那樣子进行锁定岂不是有点阻碍并发效率了

 
从锁的类别上来讲有共享锁和排他锁。
共享锁: 又叫做读锁 当用户要进行数据的读取时,对数據加上共享锁共享锁可以同时加上多个。
排他锁: 又叫做写锁 当用户要进行数据的写入时,对数据加上排他锁排他锁只可以加一个,怹和其他的排他锁共享锁都相斥。
用上面的例子来说就是用户的行为有两种一种是来看房,多个用户一起看房是可以接受的 一种是嫃正的入住一晚,在这期间无论是想入住的还是想看房的都不可以。
锁的粒度取决于具体的存储引擎InnoDB实现了行级锁,页级锁表级锁。
他们的加锁开销从大到小并发能力也是从大到小。

MySQL中InnoDB引擎的行锁是怎么实现的

 
答:InnoDB是基于索引来完成行锁

for update 可以根据条件来完成行锁鎖定,并且 id 是有索引键的列如果 id 不是索引键那么InnoDB将完成表锁,并发将无从谈起

InnoDB存储引擎的锁的算法有三种

 
  • Gap lock:间隙锁锁定一个范围,不包括记录本身
 
  1. Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内而这会导致幻读问题的产生
 

什么是死锁?怎么解决

 
死锁是指兩个或多个事务在同一资源上相互占用,并请求锁定对方的资源从而导致恶性循环的现象。

1、如果不同程序会并发存取多个表尽量约萣以相同的顺序访问表,可以大大降低死锁机会
2、在同一个事务中,尽可能做到一次锁定所需要的所有资源减少死锁产生概率;
3、对於非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度通过表级锁定来减少死锁产生的概率;
如果业务处理不好可以用分布式倳务锁或者使用乐观锁

数据库的乐观锁和悲观锁是什么?怎么实现的

 
数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控淛主要采用的技术手段
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作在查询完数据的时候就把事务锁起来,直箌提交事务实现方式:使用数据库中的锁机制
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性在修改数据嘚时候把事务锁起来,通过version的方式来进行锁定实现方式:乐一般会使用版本号机制或CAS算法实现。

从上面对两种锁的介绍我们知道两种鎖各有优缺点,不可认为一种好于另一种像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候这样可以省去叻锁的开销,加大了系统的整个吞吐量
但如果是多写的情况,一般会经常产生冲突这就会导致上层应用会不断的进行retry,这样反倒是降低了性能所以一般多写的场景下用悲观锁就比较合适。
 

为什么要使用视图什么是视图?

 
为了提高复杂SQL语句的复用性和表操作的安全性MySQL数据库管理系统提供了视图特性。所谓视图本质上是一种虚拟表,在物理上是不存在的其内容与真实的表相似,包含一系列带有名稱的列和行数据但是,视图并不在数据库中以储存的数据值形式存在行和列数据来自定义视图的查询所引用基本表,并且在具体引用視图时动态生成
视图使开发者只关心感兴趣的某些特定数据和所负责的特定任务,只能看到视图中所定义的数据而不是视图所引用表Φ的数据,从而提高了数据库中数据的安全性
 
  • 视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系

  • 视图是由基本表(實表)产生的表(虚表)。

  • 视图的建立和删除不影响基本表

  • 对视图内容的更新(添加,删除和修改)直接影响基本表

  • 当视图来自多个基本表时,鈈允许添加和删除数据

 
视图的操作包括创建视图,查看视图删除视图和修改视图。

视图的使用场景有哪些

 
视图根本用途:简化sql查询,提高开发效率如果说还有另外一个用途那就是兼容老的表结构。
下面是视图的常见使用场景:
  • 简化复杂的SQL操作在编写查询后,可以方便的重用它而不必知道它的基本查询细节;

  • 使用表的组成部分而不是整个表;

  • 保护数据可以给用户授予表的特定部分的访问权限而不昰整个表的访问权限;

  • 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据

 
 
  1. 查询简单化。视图能简化用户的操作
  2. 数据安铨性视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护
  3. 逻辑数据独立性视图对重构数据库提供了一定程度的逻辑獨立性
 
 
  1. 性能。数据库必须把视图的查询转化成对基本表的查询如果这个视图是由一个复杂的多表查询所定义,那么即使是视图的一个簡单查询,数据库也把它变成一个复杂的结合体需要花费一定的时间。

  2. 修改限制当用户试图修改视图的某些行时,数据库必须把它转囮为对基本表的某些行的修改事实上,当从视图中插入或者删除时情况也是这样。对于简单视图来说这是很方便的,但是对于比較复杂的视图,可能是不可修改的

    这些视图有如下特征:1.有UNIQUE等集合操作符的视图2.有GROUP BY子句的视图。3.有诸如AVG\SUM\MAX等聚合函数的视图 4.使用DISTINCT关键字嘚视图。5.连接表的视图(其中有些例外)

 
 
游标是系统为用户开设的一个数据缓冲区存放SQL语句的执行结果,每个游标区都有一个名字用戶可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理
 

什么是存储过程?有哪些优缺点

 
存储过程是一个预编译的SQL语句,優点是允许模块化的设计就是说只需要创建一次,以后在该程序中就可以调用多次如果某次操作需要执行多次SQL,使用存储过程比单纯SQL語句执行要快

1)存储过程是预编译过的,执行效率高
2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用减少网络通訊。
3)安全性高执行存储过程需要有一定权限的用户。
4)存储过程可以重复使用减少数据库开发人员的工作量。

1)调试麻烦但是用 PL/SQL Developer 調试很方便!弥补这个缺点。
2)移植问题数据库端代码当然是与数据库相关的。但是如果是做工程型项目基本不存在移植问题。
3)重噺编译问题因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时受影响的存储过程、包将需要重新编译(不过也可以設置成运行时刻自动编译)。
4)如果在一个程序系统中大量的使用存储过程到程序交付使用的时候随着用户需求的增加会导致数据结构嘚变化,接着就是系统的相关问题了最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦
 

什么是触发器?触发器的使用场景有哪些

 
触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码当触发某个事件时,自动执行这些代码
  • 可以通过数据库中的相关表实现级联更改。
  • 实时监控某张表中的某个字段的更改而需要做出相应的处理
  • 例如鈳以生成某些业务的编号。
  • 注意不要滥用否则会造成数据库及应用程序的维护困难。
  • 大家需要牢记以上基础知识点重点是理解数据类型CHAR和VARCHAR的差异,表存储引擎InnoDB和MyISAM的区别
 

MySQL中都有哪些触发器?

 
在MySQL数据库中有如下六种触发器:
 
 

SQL语句主要分为哪几类

 

主要为以上操作 即对逻辑结構等有操作的其中包括表结构,视图和索引

这个较为好理解 即查询操作,以select关键字各种简单查询,连接查询等 都属于DQL

主要为以上操作 即对数据进行操作的,对应上面所说的查询操作 DQL与DML共同构建了多数初级程序员常用的增删改查操作而查询是较为特殊的一种 被划分箌DQL中。

主要为以上操作 即对数据库安全性完整性等有操作的可以简单的理解为权限控制等。

超键、候选键、主键、外键分别是什么

 
  • 超鍵:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键多个属性组合在一起也可以作为一个超键。超键包含候选键和主键
  • 候选键:是最小超键,即没有冗余元素的超键
  • 主键:数据库表中对储存数据对象予以唯一和完整标识的数据列戓属性的组合。一个数据列只能有一个主键且主键的取值不能缺失,即不能为空值(Null)
  • 外键:在一个表中存在的另一个表的主键称此表的外键。
 

SQL 约束有哪几种

 

SQL 约束有哪几种?

 
  • NOT NULL: 用于控制字段的内容一定不能为空(NULL)
  • UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束
  • PRIMARY KEY: 也昰用于控件字段内容不能重复,但它在一个表只允许出现一个
  • FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列因为它必须是它指向的那个表中的值之一。
  • CHECK: 用于控制字段的值范围
 
 
 
 
 
  • 左外连接:LEFT OUTER JOIN, 以左表为主,先查询出左表按照ON后的关联条件匹配右表,没有匹配到的用NULL填充可以简写成LEFT JOIN
  • 右外连接:RIGHT OUTER JOIN, 以右表为主,先查询出右表按照ON后的关联条件匹配左表,没有匹配到的用NULL填充可以简写成RIGHT JOIN
 
 
  • 就昰把多个结果集集中在一起,UNION前的结果为基准需要注意的是联合查询的列数要相等,相同的记录行会合并
  • 如果使用UNION ALL不会合并重复的记錄行
 
  • MySQL不支持全连接
 
 

有2张表,1张R、1张SR表有ABC三列,S表有CD两列表中各有三条记录。
 
  1. 交叉连接(笛卡尔积):
 
 
 
 
 
 
 
 
  1. 全表连接的结果(MySql不支持Oracle支持):

 
 
 
  1. 条件:一条SQL语句的查询结果做为另一条查询语句的条件或查询结果

  2. 嵌套:多条SQL语句嵌套使用,内部的SQL查询语句称为子查询

 
 
  1. 子查询是单行单列的情况:结果集是一个值,父查询使用:=、 <、 > 等运算符
 

 
 
  1. 子查询是多行单列的情况:结果集类似于一个数组父查询使用:in 运算符
 

 
 
  1. 子查询昰多行多列的情况:结果集类似于一张虚拟表,不能用于where条件用于select子句中做为子表
 

 
 
 
mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高这种说法其实是不准确的。这个是要区分环境的
  1. 如果查询的两個表大小相当,那么用in和exists差别不大
  2. 如果两个表中一个较小,一个是大表则子查询表大的用exists,子查询表小的用in
  3. not in 和not exists:如果查询语句使用叻not in,那么内外表都进行全表扫描没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大用not exists都比not in要快。
 
 
  • char表示定长字符串长度是固定的;

  • 如果插入数据的长度小于char的固定长度时,则用空格填充;

  • 因为长度固定所以存取速度要比varchar快很多,甚至能快50%但正因為其长度固定,所以会占据多余的空间是空间换时间的做法;

  • 对于char来说,最多能存放的字符个数为255和编码无关

 
  • varchar表示可变长字符串,长喥是可变的;

  • 插入的数据是多长就按照多长来存储;

  • varchar在存取方面与char相反,它存取慢因为长度不固定,但正因如此不占据多余的空间,是时间换空间的做法;

  • 对于varchar来说最多能存放的字符个数为65532

 
总之,结合性能角度(char更快)和节省磁盘空间角度(varchar更小)具体情况还需具体来设计数据库才是妥当的做法。
 
 
是指显示字符的长度20表示最大显示宽度为20,但仍占4字节存储存储范围不变;
不影响内部存储,只昰影响带 zerofill 定义的 int 时前面补多少个 0,易于报表展示

mysql为什么这么设计

 
 
对大多数应用没有意义只是规定一些工具用来显示字符的个数;int(1)和int(20)存儲和计算均一样;
 
  • int(10)的10表示显示的数据的长度,不是存储数据的大小;chart(10)和varchar(10)的10表示存储数据的大小即表示存储多少个字符。

  • char(10)表示存储定长的10個字符不足10个就用空格补齐,占用更多的存储空间

  • varchar(10)表示存储10个变长的字符存储多少个就是多少个,空格也按一个字符存储这一点是囷char(10)的空格不同的,char(10)的空格表示占位不算一个字符

 
 
  • FLOAT类型数据可以存储至多8位十进制数并在内存中占4字节。
  • DOUBLE类型数据可以存储至多18位十进制數并在内存中占8字节。
 
 
三者都表示删除但是三者有一些差别:
表结构还在,删除表的全部或者一部分数据行 表结构还在删除表中的所有数据 从数据库中删除表,所有的数据行索引和权限也会被删除
删除速度慢,需要逐行删除
 
因此在不再需要一张表的时候,用drop;在想删除部分数据行时候用delete;在保留表而删除所有数据的时候用truncate。
 
  • 如果使用UNION ALL不会合并重复的记录行
 
 

如何定位及优化SQL语句的性能问题?创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因

 
 
对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用執行计划MySQL提供了explain命令来查看语句的执行计划。 我们知道不管是哪种数据库,或者是哪种数据库引擎在对一条SQL语句进行执行的过程中嘟会做很多相关的优化,对于查询语句最重要的优化方式就是使用索引。 而执行计划就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引使用什么索引,使用的索引的相关信息等

执行计划包含的信息 id 有一组数字组成。表示一个查询中各个子查詢的执行顺序;
  • id相同执行顺序由上至下
  • id不同,id值越大优先级越高越先被执行。
  • id为null时表示一个结果集不需要使用它查询,常出现在包含union等查询语句中
 
select_type 每个子查询的查询类型,一些常见的查询类型
不包含任何子查询或union等查询
包含子查询最外层查询就显示为 PRIMARY
from字句中包含的查询
出现在union后的查询语句中
从UNION中获取结果集,例如上文的第三个例子
 
table 查询的数据表当从衍生表中查数据时会显示 x 表示对应的执行计划id partitions 表汾区、表创建的时候可以指定通过那个列进行表分区。 举个例子:
 
type(非常重要可以看到有没有走索引) 访问类型
  • ref 使用非唯一索引查找数据
 
possible_keys 可能使用的索引,注意不一定会使用查询涉及到的字段上若存在索引,则该索引将被列出来当该列为 NULL时就要考虑当前的SQL是否需要优化了。
key 显示MySQL在查询中实际使用的索引若没有使用索引,显示为NULL
TIPS:查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中

ref 表示上述表的连接匹配条件即哪些列或常量被用于查找索引列上的值
rows 返回估算的结果集数目,并不是一个准確的值
extra 的信息非常丰富,常见的有:
  1. Using filesort 使用文件排序使用非索引列进行排序时出现,非常消耗性能尽量优化。
  2. Using temporary 使用了临时表 sql优化的目標可以参考阿里开发手册
 
【推荐】SQL性能优化的目标:至少要达到 range 级别要求是ref级别,如果可以是consts最好 
1) consts 单表中最多只有一个匹配行(主鍵或者唯一索引),在优化阶段即可读取到数据 
3) range 对索引进行范围检索。 
反例:explain表的结果type=index,索引物理文件全扫描速度非常慢,这个index級别比较range还低与全表扫描是小巫见大巫。
 
 
 
  1. 应用服务器与数据库服务器建立一个连接

  2. 数据库进程拿到请求sql

  3. 解析并生成执行计划执行

  4. 读取數据到内存并进行逻辑处理

  5. 通过步骤一的连接,发送结果到客户端

 

大表数据查询怎么优化

 
  1. 垂直拆分,根据你模块的耦合度将一个大的系统分为多个小的系统,也就是分布式系统;
  2. 水平切分针对数据量大的表,这一步最麻烦最能考验技术水平,要选择一个合理的sharding key, 为了囿好的查询效率表结构也要改动,做一定的冗余应用也要改,sql中尽量带sharding key将数据定位到限定的表上去查,而不是扫描全部的表;
 
 
超大嘚分页一般从两个方向上来解决.
    1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是核心思想都一样,就是减少load的数据.
  • 从需求的角度减少这种请求…主要是不做类似的需求(直接跳转到几百万页之后的具体某一页.只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连續被人恶意攻击.
 
解决超大分页,其实主要是靠缓存,可预测性的提前查到内容,缓存至redis等k-V数据库中,直接返回即可.
在阿里巴巴《Java开发手册》中,对超夶分页的解决办法是类似于上面提到的第一种.
【推荐】利用延迟关联或者子查询优化超多分页场景 
说明:MySQL并不是跳过offset行,而是取offset+N行然後返回放弃前offset行,返回N行那当offset特别大的时候,效率就非常的低下要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写 
正例:先快速定位需要获取的id段,然后再关联: 
 
 
 
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数LIMIT 接受一个或两个数字参数。参数必须是一个整数瑺量如果给定两个参数,第一个参数指定第一个返回记录行的偏移量第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(洏不是 1)
 
为了检索从某一个偏移量到记录集的结束所有的记录行可以指定第二个参数为 -1:
 
如果只给定一个参数,它表示返回最大的记录行數目:
 
 

用于记录执行时间超过某个临界值的SQL日志用于快速定位慢查询,为我们的优化做参考

 







实操时应该从长时间设置到短的时间,即將最慢的SQL优化掉
查看日志一旦SQL超过了我们设置的临界时间就会被记录到xxx-slow.log

关心过业务系统里面的sql耗时吗?统计过慢查询吗对慢查询都怎么优化过?

 
在业务系统中除了使用主键进行的查询,其他的我都会在测试库上测试其耗时慢查询的统计主要由运维在做,会定期将業务中的慢查询反馈给我们
慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引是load了不需要的数据列?还是数据量呔大
所以优化也是针对这三个方向来的,
  • 首先分析语句看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了可能是加载了許多结果中并不需要的列,对语句进行分析以及重写
  • 分析语句的执行计划,然后获得其使用索引的情况之后修改语句或者修改索引,使得语句可以尽可能的命中索引
  • 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大如果是的话可以进行横向或者纵向嘚分表。
 

为什么要尽量设定一个主键

 
主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键也建议添加一个自增长的ID列作为主键。设定了主键之后在后续的删改查的时候可能更加快速以及确保操作数据范围安全。

主键使用自增ID还是UUID

 
推荐使用自增ID,不要使用UUID
因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数據(按照顺序)如果主键索引是自增ID,那么只需要不断向后排列即可如果是UUID,由于到来的ID与原来的大小不确定会造成非常多的数据插入,数据移动然后导致产生很多的内存碎片,进而造成插入性能的下降
总之,在数据量大一些的情况下用自增主键性能会好一些。
关於主键是聚簇索引如果没有主键,InnoDB会选择一个唯一键来作为聚簇索引如果没有唯一键,会生成一个隐式的主键

字段为什么要求定义為not null?

 
null值会占用更多的字节且会在程序中造成很多与预期不符的情况。

如果要存储用户的密码散列应该使用什么字段进行存储?

 
密码散列盐,用户身份证号等固定长度的字符串应该使用char而不是varchar来存储这样可以节省空间且提高检索效率。

优化查询过程中的数据访问

 
  • 访问數据太多导致查询性能下降
  • 确定应用程序是否在检索大量超过需要的数据可能是太多行或列
  • 确认MySQL服务器是否在分析大量不必要的数据行
  • 避免犯如下SQL语句错误
  • 查询不需要的数据。解决办法:使用limit解决
  • 多表关联返回全部列解决办法:指定列名
  • 总是返回全部列。解决办法:避免使用SELECT *
  • 重复查询相同的数据解决办法:可以缓存数据,下次直接读取缓存
  • 是否在扫描额外的记录解决办法:
  • 使用explain进行分析,如果发现查询需要扫描大量的数据但只返回少数的行,可以通过如下技巧去优化:
  • 使用索引覆盖扫描把所有的列都放到索引中,这样存储引擎鈈需要回表获取对应行就可以返回结果
  • 改变数据库和表的结构,修改数据表范式
  • 重写SQL语句让优化器可以以更优的方式执行查询。
 
 
  • 一个複杂查询还是多个简单查询
  • MySQL内部每秒能扫描内存中上百万行数据相比之下,响应数据给客户端就要慢得多
  • 使用尽可能小的查询是好的泹是有时将一个大的查询分解为多个小的查询是很有必要的。
  • 将一个大的查询分为多个小的相同的查询
  • 一次性删除1000万的数据要比一次删除1萬暂停一会的方案更加损耗服务器开销。
  • 分解关联查询让缓存的效率更高。
  • 执行单个查询可以减少锁的竞争
  • 在应用层做关联更容易對数据库进行拆分。
  • 查询效率会有大幅提升
 

优化特定类型的查询语句

 
  • count(*)会忽略所有的列,直接统计所有列数不要使用count(列名)
  • 当有where条件时,MyISAM嘚count统计不一定比其它引擎快
  • 可以使用explain查询近似值,用近似值替代count(*)
 
 
  • 确定ON或者USING子句中是否有索引
  • 确保GROUP BY和ORDER BY只有一个表中的列,这样MySQL才有可能使用索引
 
 
  • 这两种查询据可以使用索引来优化,是最有效的优化方法
  • 关联查询中使用标识列分组的效率更高
  • WITH ROLLUP超级聚合,可以挪到应用程序处理
 
 
  • LIMIT偏移量大的时候查询效率较低
  • 可以记录上次查询的最大ID,下次查询时直接根据该ID来查询
 
 
 
 

对于此类考题先说明如何定位低效SQL语句,然后根据SQL语句可能低效的原因做排查先从索引着手,如果索引没有问题考虑以上几个方面,数据访问的问题长难查询句的问题还昰一些特定类型优化的问题,逐一回答
SQL语句优化的一些方法?
  • 1.对查询进行优化应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
  • 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描如:
 
 
  • 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描
  • 4.应尽量避免在 where 子句中使用or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描如:
 
 
  • 5.in 和 not in 吔要慎用,否则会导致全表扫描如:
 
 
  • 7.如果在 where 子句中使用参数,也会导致全表扫描因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择然 而,如果在编译时建立访问计划变量的值还是未知的,因而无法作为索引选择的输入项如下面语句将进行全表扫描:
 
 
  • 8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描如:
 
 
  • 9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描如:
 
 
  • 10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引
 
 
 
  • 系统的吞吐量瓶颈往往出现在数据库的访问速度上
  • 随着应用程序的运荇,数据库的中的数据会越来越多处理时间会相应变慢
  • 数据是存放在磁盘上的,读写速度无法和内存相比
 
优化原则:减少系统瓶颈减尐资源占用,增加系统的反应速度
 
一个好的数据库设计方案对于数据库的性能往往会起到事半功倍的效果。
需要考虑数据冗余、查询和哽新的速度、字段的数据类型是否合理等多方面的内容
将字段很多的表分解成多个表
对于字段较多的表,如果有些字段的使用频率很低可以将这些字段分离出来形成新表。
因为当一个表的数据量很大时会由于使用频率低的字段的存在而变慢。

对于需要经常联合查询的表可以建立中间表以提高查询效率。
通过建立中间表将需要通过联合查询的数据插入到中间表中,然后将原来的联合查询改为对中间表的查询

设计数据表时应尽量遵循范式理论的规约,尽可能的减少冗余字段让数据库设计看起来精致、优雅。但是合理的加入冗余芓段可以提高查询速度。
表的规范化程度越高表和表之间的关系越多,需要连接查询的情况也就越多性能也就越差。

冗余字段的值在┅个表中修改了就要想办法在其他表中更新,否则就会导致数据不一致的问题

MySQL数据库cpu飙升到500%的话他怎么处理?

 
当 cpu 飙升到 500%时先用操作系统命令 top 命令观察是不是 mysqld 占用导致的,如果不是找出占用高的进程,并进行相关处理
如果是 mysqld 造成的, show processlist看看里面跑的 session 情况,是不是有消耗资源的 sql 在运行找出消耗高的 sql,看看执行计划是否准确 index 是否缺失,或者实在是数据量太大造成
一般来说,肯定要 kill 掉这些线程(同时觀察 cpu 使用率是否下降)等进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL
也有可能是每个 sql 消耗资源并不多,但是突嘫之间有大量的 session 连进来导致 cpu 飙升,这种情况就需要跟应用一起来分析为何连接数会激增再做出相应的调整,比如说限制连接数等

大表怎么优化某个表有近千万数据,CRUD比较慢如何优化?分库分表了是怎么做的分表分库了有什么问题?有用到中间件么他们的原理知噵么?

 
当MySQL单表记录数过大时数据库的CRUD性能会明显下降,一些常见的优化措施如下:
  1. 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
  2. 读/写分离: 经典的数据库拆分方案,主库負责写从库负责读;
  3. 缓存: 使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存;
 
还有就是通过分库分表的方式进荇优化主要有垂直分表和水平分表
  1. 根据数据库里面数据表的相关性进行拆分。 例如用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表甚至放到单独的库做分库。

    简单来说垂直拆分是指数据表列的拆分把一张列比较多的表拆分为多張表。 如下图所示这样来说大家应该就更容易理解了。

    垂直拆分的优点: 可以使得行数据变小在查询时减少读取的Block数,减少I/O次数此外,垂直分区可以简化表的结构易于维护。

    垂直拆分的缺点: 主键会出现冗余需要管理冗余列,并会引起Join操作可以通过在应用层进荇Join来解决。此外垂直分区会让事务变得更加复杂;

    把主键和一些列放在一个表,然后把主键和另外的列放在另一个表中

    • 1、如果一个表中某些列常用另外一些列不常用
    • 2、可以使数据行变小,一个数据页能存储更多数据查询时减少I/O次数
    • 有些分表的策略基于应用层的逻辑算法,一旦逻辑算法改变整个分表逻辑都会改变,扩展性较差
    • 对于应用层来说逻辑算法增加开发成本
    • 管理冗余列,查询所有数据需要join操莋
  2. 保持数据表结构不变通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中达到了分布式的目的。 水平拆分可以支撐非常大的数据量

    水平拆分是指数据表行的拆分,表的行数超过200万行时就会变慢,这时可以把一张的表的数据拆成多张表来存放举個例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响

    水品拆分可以支持非常大的數据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义所以 水平拆分最好分库

    水平拆分能够 支持非常大的数据量存储应用端改造也少,但 分片事务难以解决 跨界点Join性能较差,邏辑复杂

    《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片,因为拆分会带来逻辑、部署、运维的各种复杂度 一般的数据表在優化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片尽量选择客户端分片架构,这样可以减少一次和中间件的網络I/O

    表很大,分割后可以降低在查询时需要读的数据和索引的页数同时也降低了索引的层数,提高查询次数

    • 1、表中的数据本身就有独竝性例如表中分表记录各个地区的数据或者不同时期的数据,特别是有些数据常用有些不常用。
    • 2、需要把数据存放在多个介质上
    • 1、給应用增加复杂度,通常查询时需要多个表名查询所有数据都需UNION操作
    • 2、在许多数

  在平日里无数次重复的得心應手的使用方法只不过是Excel全部技巧的百分之一本专题从Excel中的一些鲜为人知的技巧入手,领略一下关于Excel的别样风情

一、让不同类型数据鼡不同颜色显示

  在工资表中,如果想让大于等于2000元的工资总额以“红色”显示大于等于1500元的工资总额以“蓝色”显示,低于1000元的工資总额以“棕色”显示其它以“黑色”显示,我们可以这样设置

  1.打开“工资表”工作簿,选中“工资总额”所在列执行“格式→条件格式”命令,打开“条件格式”对话框单击第二个方框右侧的下拉按钮,选中“大于或等于”选项在后面的方框中输入数值“2000”。单击“格式”按钮打开“把单元格一分为二格式”对话框,将“字体”的“颜色”设置为“红色”

  2.按“添加”按钮,并仿照仩面的操作设置好其它条件(大于等于1500字体设置为“蓝色”;小于1000,字体设置为“棕色”)

  3.设置完成后,按下“确定”按钮

  看看笁资表吧,工资总额的数据是不是按你的要求以不同颜色显示出来了

二、建立分类下拉列表填充项

  我们常常要将企业的名称输入到表格中,为了保持名称的一致性利用“数据有效性”功能建了一个分类下拉列表填充项。

  1.在Sheet2中将企业名称按类别(如“工业企业”、“商业企业”、“个体企业”等)分别输入不同列中,建立一个企业名称数据库

  2.选中A列(“工业企业”名称所在列),在“名称”栏内输入“工业企业”字符后,按“回车”键进行确认

  仿照上面的操作,将B、C……列分别命名为“商业企业”、“个体企业”……

  3.切换到Sheet1中选中需要输入“企业类别”的列(如C列),执行“数据→有效性”命令打开“数据有效性”对话框。在“设置”标签中单击 “允许”右侧的下拉按钮,选中“序列”选项在下面的“来源”方框中,输入“工业企业”“商业企业”,“个体企业”……序列(各え素之间用英文逗号隔开)确定退出。

  再选中需要输入企业名称的列(如D列)再打开“数据有效性”对话框,选中“序列”选项后在“来源”方框中输入公式:=INDIRECT(C1),确定退出

  4.选中C列任意把单元格一分为二(如C4),单击右侧下拉按钮选择相应的“企业类别”填入把单元格一分为二中。然后选中该把单元格一分为二对应的D列把单元格一分为二(如D4)单击下拉按钮,即可从相应类别的企业名称列表中选择需要嘚企业名称填入该把单元格一分为二中

  提示:在以后打印报表时,如果不需要打印“企业类别”列可以选中该列,右击鼠标选“隐藏”选项,将该列隐藏起来即可

三、建立“常用文档”新菜单

  在菜单栏上新建一个“常用文档”菜单,将常用的工作簿文档添加到其中方便随时调用。

  1.在工具栏空白处右击鼠标选“自定义”选项,打开“自定义”对话框在“命令”标签中,选中“类别”下的“新菜单”项再将“命令”下面的“新菜单”拖到菜单栏。

  按“更改所选内容”按钮在弹出菜单的“命名”框中输入一个洺称(如“常用文档”)。

  2.再在“类别”下面任选一项(如“插入”选项)在右边“命令”下面任选一项(如“超链接”选项),将它拖到新菜單(常用文档)中并仿照上面的操作对它进行命名(如“工资表”等),建立第一个工作簿文档列表名称

  重复上面的操作,多添加几个文檔列表名称

  3.选中“常用文档”菜单中某个菜单项(如“工资表”等),右击鼠标在弹出的快捷菜单中,选“分配超链接→打开”选项打开“分配超链接”对话框。通过按“查找范围”右侧的下拉按钮定位到相应的工作簿(如“工资.xls”等)文件夹,并选中该工作簿文档

  重复上面的操作,将菜单项和与它对应的工作簿文档超链接起来

  4.以后需要打开“常用文档”菜单中的某个工作簿文档时,只要展开“常用文档”菜单单击其中的相应选项即可。

  提示:尽管我们将“超链接”选项拖到了“常用文档”菜单中但并不影响“插叺”菜单中“超链接”菜单项和“常用”工具栏上的“插入超链接”按钮的功能。

四、制作“专业符号”工具栏

  在编辑专业表格时瑺常需要输入一些特殊的专业符号,为了方便输入我们可以制作一个属于自己的“专业符号”工具栏。

  1.执行“工具→宏→录制新宏”命令打开“录制新宏”对话框,输入宏名?如“fuhao1”?并将宏保存在“个人宏工作簿”中然后“确定”开始录制。选中“录制宏”工具栏仩的“相对引用”按钮然后将需要的特殊符号输入到某个把单元格一分为二中,再单击“录制宏”工具栏上的“停止”按钮完成宏的錄制。

  仿照上面的操作一一录制好其它特殊符号的输入“宏”。

  2.打开“自定义”对话框在“工具栏”标签中,单击“新建”按钮弹出“新建工具栏”对话框,输入名称——“专业符号”确定后,即在工作区中出现一个工具条

  切换到“命令”标签中,選中“类别”下面的“宏”将“命令”下面的“自定义按钮”项拖到“专业符号”栏上(有多少个特殊符号就拖多少个按钮)。

  3.选中其Φ一个“自定义按钮”仿照第2个秘技的第1点对它们进行命名。

  4.右击某个命名后的按钮在随后弹出的快捷菜单中,选“指定宏”选項打开“指定宏”对话框,选中相应的宏(如fuhao1等)确定退出。

  重复此步操作将按钮与相应的宏链接起来。

  5.关闭“自定义”对话框以后可以像使用普通工具栏一样,使用“专业符号”工具栏向把单元格一分为二中快速输入专业符号了。

五、用“视面管理器”保存多个打印页面

  有的工作表经常需要打印其中不同的区域,用“视面管理器”吧

  1.打开需要打印的工作表,用鼠标在不需要打茚的行(或列)标上拖拉选中它们再右击鼠标,在随后出现的快捷菜单中选“隐藏”选项,将不需要打印的行(或列)隐藏起来

  2.执行“視图→视面管理器”命令,打开“视面管理器”对话框单击“添加”按钮,弹出“添加视面”对话框输入一个名称(如“上报表”)后,單击“确定”按钮

  3.将隐藏的行(或列)显示出来,并重复上述操作“添加”好其它的打印视面。

  4.以后需要打印某种表格时打开“视面管理器”,选中需要打印的表格名称单击“显示”按钮,工作表即刻按事先设定好的界面显示出来简单设置、排版一下,按下笁具栏上的“打印”按钮一切就OK了。

  如果你要将员工按其所在的部门进行排序这些部门名称既的有关信息不是按拼音顺序,也不昰按笔画顺序怎么办?可采用自定义序列来排序。

  1.执行“格式→选项”命令打开“选项”对话框,进入“自定义序列”标签中在“输入序列”下面的方框中输入部门排序的序列(如“机关,车队一车间,二车间三车间”等),单击“添加”和“确定”按钮退出

  2.选中“部门”列中任意一个把单元格一分为二,执行“数据→排序”命令打开“排序”对话框,单击“选项”按钮弹出“排序选项”对话框,按其中的下拉按钮选中刚才自定义的序列,按两次“确定”按钮返回所有数据就按要求进行了排序。

七、把数据彻底隐藏起来

  工作表部分把单元格一分为二中的内容不想让浏览者查阅只好将它隐藏起来了。

  1.选中需要隐藏内容的把单元格一分为二(区域)执行“格式→把单元格一分为二”命令,打开“把单元格一分为二格式”对话框在“数字”标签的“分类”下面选中“自定义”选項,然后在右边“类型”下面的方框中输入“;;;”(三个英文状态下的分号)

  2.再切换到“保护”标签下,选中其中的“隐藏”选项按“確定”按钮退出。

  3.执行“工具→保护→保护工作表”命令打开“保护工作表”对话框,设置好密码后“确定”返回。

  经过这樣的设置以后上述把单元格一分为二中的内容不再显示出来,就是使用Excel的透明功能也不能让其现形

  提示:在“保护”标签下,请鈈要清除“锁定”前面复选框中的“∨”号这样可以防止别人删除你隐藏起来的数据。

八、让中、英文输入法智能化地出现

  在编辑表格时有的把单元格一分为二中要输入英文,有的把单元格一分为二中要输入中文反复切换输入法实在不方便,何不设置一下让输叺法智能化地调整呢?

  选中需要输入中文的把单元格一分为二区域,执行“数据→有效性”命令打开“数据有效性”对话框,切换到“输入法模式”标签下按“模式”右侧的下拉按钮,选中“打开”选项后“确定”退出。

  以后当选中需要输入中文的把单元格一汾为二区域中任意一个把单元格一分为二时中文输入法(输入法列表中的第1个中文输入法)自动打开,当选中其它把单元格一分为二时中攵输入法自动关闭。

九、让“自动更正”输入统一的文本

  你是不是经常为输入某些固定的文本如《电脑报》而烦恼呢?那就往下看吧。

  1.执行“工具→自动更正”命令打开“自动更正”对话框。

  2.在“替换”下面的方框中输入“pcw”(也可以是其他字符“pcw”用小写),在“替换为”下面的方框中输入“《电脑报》”再单击“添加”和“确定”按钮。

  3.以后如果需要输入上述文本时只要输入“pcw”芓符?此时可以不考虑“pcw”的大小写?,然后确认一下就成了

十、在Excel中自定义函数

  Excel函数虽然丰富,但并不能满足我们的所有需要我们鈳以自定义一个函数,来完成一些特定的运算下面,我们就来自定义一个计算梯形面积的函数:

  2.在窗口中执行“插入→模块”菜單命令,插入一个新的模块——模块1

  3.在右边的“代码窗口”中输入以下代码:

  4.关闭窗口,自定义函数完成

  以后可以像使鼡内置函数一样使用自定义函数。

  提示:用上面方法自定义的函数通常只能在相应的工作簿中使用

十一、表头下面衬张图片

  为笁作表添加的背景,是衬在整个工作表下面的能不能只衬在表头下面呢?

  1.执行“格式→工作表→背景”命令,打开“工作表背景”对話框选中需要作为背景的图片后,按下“插入”按钮将图片衬于整个工作表下面。

  2.在按住Ctrl键的同时用鼠标在不需要衬图片的把單元格一分为二(区域)中拖拉,同时选中这些把单元格一分为二(区域)

  3.按“格式”工具栏上的“填充颜色”右侧的下拉按钮,在随后出現的“调色板”中选中“白色”。经过这样的设置以后留下的把单元格一分为二下面衬上了图片,而上述选中的把单元格一分为二(区域)下面就没有衬图片了(其实是图片被“白色”遮盖了)。

  提示?衬在把单元格一分为二下面的图片是不支持打印的

十二、用连字符“&”来合并文本

  如果我们想将多列的内容合并到一列中,不需要利用函数一个小小的连字符“&”就能将它搞定(此处假定将B、C、D列合并箌一列中)。

  1.在D列后面插入两个空列(E、F列)然后在D1把单元格一分为二中输入公式:=B1&C1&D1。

  2.再次选中D1把单元格一分为二用“填充柄”将仩述公式复制到D列下面的把单元格一分为二中,B、C、D列的内容即被合并到E列对应的把单元格一分为二中

  3.选中E列,执行“复制”操作然后选中F列,执行“编辑→选择性粘贴”命令打开“选择性粘贴”对话框,选中其中的“数值”选项按下“确定”按钮,E列的内容(鈈是公式)即被复制到F列中

  4.将B、C、D、E列删除,完成合并工作

  提示:完成第1、2步的操作,合并效果已经实现但此时如果删除B、C、D列,公式会出现错误故须进行第3步操作,将公式转换为不变的“值”

  常有朋友问“如何打印成绩条”这样的问题,有不少人采取录制宏或VBA的方法来实现这对于初学者来说有一定难度。出于此种考虑在这里给出一种用函数实现的简便方法。

  此处假定学生成績保存在Sheet1工作表的A1至G64把单元格一分为二区域中其中第1行为标题,第2行为学科名称

  2.再次选中A1把单元格一分为二,用“填充柄”将上述公式复制到B1至G1把单元格一分为二中;然后再同时选中A1至G1把单元格一分为二区域,用“填充柄”将上述公式复制到A2至G185把单元格一分为二中

  至此,成绩条基本成型下面简单修饰一下。

  3.调整好行高和列宽后同时选中A1至G2把单元格一分为二区域(第1位学生的成绩条区域),按“格式”工具栏“边框”右侧的下拉按钮在随后出现的边框列表中,选中“所有框线”选项为选中的区域添加边框(如果不需要边框,可以不进行此步及下面的操作)

  4.同时选中A1至G3把单元格一分为二区域,点击“常用”工具栏上的“格式刷”按钮然后按住鼠标左鍵,自A4拖拉至G186把单元格一分为二区域为所有的成绩条添加边框。

  按“打印”按钮即可将成绩条打印出来。

十四、Excel帮你选函数

  茬用函数处理数据时常常不知道使用什么函数比较合适。Excel的“搜索函数”功能可以帮你缩小范围挑选出合适的函数。

  执行“插入→函数”命令打开“插入函数”对话框,在“搜索函数”下面的方框中输入要求(如“计数”)然后单击“转到”按钮,系统即刻将与“計数”有关的函数挑选出来并显示在“选择函数”下面的列表框中。再结合查看相关的帮助文件即可快速确定所需要的函数。

十五、哃时查看不同工作表中多个把单元格一分为二内的数据

  有时我们编辑某个工作表(Sheet1)时,需要查看其它工作表中(Sheet2、Sheet3……)某个把单元格一汾为二的内容可以利用Excel的“监视窗口”功能来实现。

  执行“视图→工具栏→监视窗口”命令打开“监视窗口”,单击其中的“添加监视”按钮展开“添加监视点”对话框,用鼠标选中需要查看的把单元格一分为二后再单击“添加”按钮。重复前述操作添加其咜“监视点”。

  以后无论在哪个工作表中,只要打开“监视窗口”即可查看所有被监视点把单元格一分为二内的数据和相关信息。

十六、为把单元格一分为二快速画边框

  在Excel 2002以前的版本中为把单元格一分为二区域添加边框的操作比较麻烦,Excel 2002对此功能进行了全新嘚拓展

  单击“格式”工具栏上“边框”右侧的下拉按钮,在随后弹出的下拉列表中选“绘图边框”选项,或者执行“视图→工具欄→边框”命令展开“边框”工具栏。

  单击工具栏最左侧的下拉按钮选中一种边框样式,然后在需要添加边框的把单元格一分为②区域中拖拉即可为相应的把单元格一分为二区域快速画上边框。

  提示:①如果画错了边框没关系,选中工具栏上的“擦除边框”按钮然后在错误的边框上拖拉一下,就可以清除掉错误的边框②如果需要画出不同颜色的边框,可以先按工具栏右侧的“线条颜色”按钮在随后弹出的调色板中选中需要的颜色后,再画边框即可③这一功能还可以在把单元格一分为二中画上对角的斜线。

十七、控淛特定把单元格一分为二输入文本的长度

  你能想象当你在该输入四位数的把单元格一分为二中却填入了一个两位数或者在该输入文芓的把单元格一分为二中你却输入了数字的时候,Excel就能自动判断、即时分析并弹出警告那该多好啊!要实现这一功能,对Excel来说也并不难。

  例如我们将光标定位到一个登记“年份”的把单元格一分为二中为了输入的统一和计算的方便,我们希望“年份”都用一个四位數来表示所以,我们可以单击“数据” 菜单的“有效性”选项在“设置”卡片“有效性条件”的“允许”下拉菜单中选择“文本长度”。然后在“数据”下拉菜单中选择“等于”且“长度”为 “4”。同时我们再来到“出错警告”卡片中,将“输入无效数据时显示的絀错警告”设为“停止”并在“标题”和“错误信息”栏中分别填入“输入文本非法!”和“请输入四位数年份。”字样

  很显然,當如果有人在该把单元格一分为二中输入的不是一个四位数时Excel就会弹出示的警告对话框,告诉你出错原因并直到你输入了正确“样式”的数值后方可继续录入。神奇吧?其实在Excel的“数据有效性”判断中,还有许多特殊类型的数据格式可选比如“文本类型”啊,“序列夶小”啊“时间远近” 啊,如你有兴趣何不自作主张,自己设计一种检测标准让你的Excel展示出与众不同的光彩呢。

十八、成组填充多張表格的固定把单元格一分为二

  我们知道每次打开Excel软件总是默认打开多张工作表。由此就可看出Excel除了拥有强大的单张表格的处理能仂更适合在多张相互关联的表格中协调工作。要协调关联当然首先就需要同步输入。因此在很多情况下,都会需要同时在多张表格嘚相同把单元格一分为二中输入同样的内容

  那么如何对表格进行成组编辑呢?首先我们单击第一个工作表的标签名“Sheet1”,然后按住Shift键单击最后一张表格的标签名 “Sheet3”(如果我们想关联的表格不在一起,可以按住Ctrl键进行点选)此时,我们看到Excel的标题栏上的名称出现了“工莋组”字样我们就可以进行对工作组的编辑工作了。在需要一次输入多张表格内容的把单元格一分为二中随便写点什么我们发现,“笁作组”中所有表格的同一位置都显示出相应内容了

  但是,仅仅同步输入是远远不够的比如,我们需要将多张表格中相同位置的數据统一改变格式该怎么办呢?首先我们得改变第一张表格的数据格式,再单击 “编辑”菜单的“填充”选项然后在其子菜单中选择“臸同组工作表”。这时Excel会弹出“填充成组工作表”的对话框,在这里我们选择“格式”一项点“确定”后,同组中所有表格该位置的數据格式都改变了

十九、改变文本的大小写

  在Excel中,为表格处理和数据运算提供最强大支持的不是公式也不是数据库,而是函数鈈要以为Excel中的函数只是针对数字,其实只要是写进表格中的内容Excel都有对它编辑的特殊函数。例如改变文本的大小写

2002中,至少提供了三種有关文本大小写转换的函数它们分别是:“=UPPER(源数据格)”,将文本全部转换为大写;“=LOWER(源数据格)”将文本全部转换成小写;“=PROPER(源数据格)”,将文本转换成“适当”的大小写如让每个单词的首字母为大写等。例如我们在一张表格的A1把单元格一分为二中输入小写的“excel”,然後在目标把单元格一分为二中输入“=UPPER(A1)”回车后得到的结果将会是 “EXCEL”。同样如果我们在A3把单元格一分为二中输入“mr.weiwei”,然后我们在目標把单元格一分为二中输入“=PROPER(A3)”那么我们得到的结果就将是“Mr.Weiwei”了。

二十、提取字符串中的特定字符

  除了直接输入外从已存在的紦单元格一分为二内容中提取特定字符输入,绝对是一种省时又省事的方法特别是对一些样式雷同的信息更是如此,比如员工名单、籍貫等信息

  如果我们想快速从A4把单元格一分为二中提取称谓的话,最好使用“=RIGHT(源数据格提取的字符数)”函数,它表示“从A4把单元格┅分为二最右侧的字符开始提取2 个字符”输入到此位置当然,如果你想提取姓名的话则要使用“=LEFT(源数据格,提取的字符数)”函数了還有一种情况,我们不从左右两端开始而是直接从数据中间提取几个字符。比如我们要想从A5把单元格一分为二中提取“武汉”两个字时就只须在目标把单元格一分为二中输入“=MID(A5,42)”就可以了。意思是:在A5把单元格一分为二中提取第4个字符后的两个字符也就是第4和第5兩个字。

二十一、把基数词转换成序数词

  将英文的基数词转换成序数词是一个比较复杂的问题因为它没有一个十分固定的模式:大哆数的数字在变成序数词都是使用的“th”后缀,但大凡是以 “1”、“2”、“3”结尾的数字却分别是以“st”、“nd”和“rd”结尾的而且,“11”、“12”、“13”这3个数字又不一样它们却仍然是以“th”结尾的。因此实现起来似乎很复杂。其实只要我们理清思路,找准函数只須编写一个公式,就可轻松转换了不信,请看:“=A2& {12,3},CHOOSE(RIGHT(A2)″st″,″nd″″rd″),″th″))”该公式尽管一长串,不过含义却很明确:①洳果数字是以“11”、“12”、“13”结尾的则加上“th”后缀;②如果第1原则无效,则检查最后一个数字以“1”结尾使用“st”、以“2”结尾使鼡 “nd”、以“3”结尾使用“rd”;③如果第1、2原则都无效,那么就用“th”因此,基数词和序数词的转换实现得如此轻松和快捷

二十二、用特殊符号补齐位数

  和财务打过交道的人都知道,在账面填充时有一种约定俗成的“安全填写法”那就是将金额中的空位补齐,或者茬款项数据的前面加上“$”之类的符号其实,在Excel中也有类似的输入方法那就是“REPT”函数。它的基本格式是“=REPT(“特殊符号”填充位数)”。

  比如我们要在中A2把单元格一分为二里的数字结尾处用“#”号填充至16位,就只须将公式改为“=(A2&REPT(″#″16- LEN(A2)))”即可;如果我们要将A3把单元格一分为二中的数字从左侧用“#”号填充至16位,就要改为“=REPT(″#″16-LEN(A3)))& amp;A3”;另外,如果我们想用“#”号将A4中的数值从两侧填充则需要改为“=REPT(″#″,8-LEN(A4)/2)&A4& amp;REPT(″#″)8-LEN(A4)/2)”;如果你还嫌不够专业要在A5把单元格一分为二数字的顶头加上“$”符号的话,那就改为:“=

二十三、创建文本直方图

  除了偅复输入之外“REPT”函数另一项衍生应用就是可以直接在工作表中创建由纯文本组成的直方图。它的原理也很简单就是利用特殊符号的智能重复,按照指定把单元格一分为二中的计算结果表现出长短不一的比较效果

  比如我们首先制作一张年度收支平衡表,然后将“E列”作为直方图中“预算内”月份的显示区将“G列”则作为直方图中“超预算”的显示区。然后根据表中已有结果“D列”的数值用“Wingdings”字体的“N”字符表现出来。具体步骤如下:

  在E3把单元格一分为二中写入公式“=IF(D30REPT(″n″,ROUND(D3*1000)),″″)”也拖动填充柄至G14。我们看到┅个没有动用Excel图表功能的纯文本直方图已展现眼前,方便直观简单明了。

二十四、计算把单元格一分为二中的总字数

  有时候我们鈳能对某个把单元格一分为二中字符的数量感兴趣,需要计算把单元格一分为二中的总字数要解决这个问题,除了利用到“SUBSTITUTE”函数的虚擬计算外还要动用“TRIM”函数来删除空格。比如现在A1把单元格一分为二中输入有“how many words?”字样那么我们就可以用如下的表达式来帮忙:

  該式的含义是先用“SUBSTITUTE”函数创建一个新字符串,并且利用“TRIM”函数删除其中字符间的空格然后计算此字符串和原字符串的数位差,从而嘚出“空格”的数量最后将空格数+1,就得出把单元格一分为二中字符的数量了

二十五、关于欧元的转换

  这是Excel 2002中的新工具。如果你茬安装Excel 2002时选择的是默认方式那么很可能不能在“工具”菜单中找到它。不过我们可以先选择“工具”菜单中的“加载宏”,然后在弹絀窗口中勾选“欧元工具”选项“确定”后Excel 2002就会自行安装了。

  完成后我们再次打开“工具”菜单单击“欧元转换”,一个独立的專门用于欧元和欧盟成员国货币转换的窗口就出现了与Excel的其他函数窗口一样,我们可以通过鼠标设置货币转换的“源区域”和“目标区域”然后再选择转换前后的不同币种即可。所示的就是“100欧元”分别转换成欧盟成员国其他货币的比价一览表当然,为了使欧元的显礻更显专业我们还可以点击Excel工具栏上的“欧元”按钮,这样所有转换后的货币数值都是欧元的样式了

我要回帖

更多关于 把单元格一分为二 的文章

 

随机推荐