1、length+;删除: for (int j = i; j = length - 1; j+) dataj-1 = dataj;3 链表的基本操作(代码)单链表开头插入:SNode newnode = new SNode(a);if (i = 1) newnode.Next = start; start = newnode; length+; return;单链表两结点间插入: current; previous;current = start;previous = null;int j = 1;while (current!= null & j i) previous = current;
2、current = current.Next;j+;if (j = i) newnode.Next = current; previous.Next = newnode;单链表末尾插入: if (start = null) start = new SNode SNode current = start; while (current.Next != null) current.Next = new SNode单链表的开头删除: start = current.Next; length-;单链表中两结点间删除: previous=null;while (current.Next ! j+; pr
3、evious.Next = current.Next; current = null;双向链表插入:使新节点的next指向当前结点;使新节点的prev指向前一个结点;使当前结点的prev指向新结点;使前一个结点的next指向新结点./双向链表的两个元素间插入一个元素 newnode.Prev = previous; if(current!=null) current.Prev = newnode;双向链表删除:DbNode if(current.Next ! current.Next.Prev = previous; previous = null;4 链表与数组的优缺点比较(问答)数组链表逻
4、辑结构上数组的存储空间是静态,连续分布的,估计过大造成空间浪费,估计太小又将使空间溢出机会增多链表动态地进行存储分配,可以适应数据动态地增减的情况,不用事先估计存储规模,但链表的存储密度较低内存存储上数组从栈中分配空间, 对于程序员方便快速,但是自由度小链表从堆中分配空间, 自由度大但是申请管理比较麻烦.数据访问上随机存取,顺序表中做插入、删除时平均移动表中一半的元素,当数据元素的信息量较大操作效率低;顺序存取,在链表中作插入、删除,虽然也要找插入位置,但操作主要是比较操作,从这个角度考虑显然后者优于前者。编程环境上数组容易实现,任何高级语言中都有数组类型链表的操作是基于指针的,相对比前者复杂
5、总之两者存储结构各有长短,选择那一种由实际问题中的主要因素决定。通常“较稳定”的线性表选择顺序存储,而频繁做插入删除的即动态性较强的线性表宜选择链式存储。顺序存储结构的特点是相对位置表示逻辑关系,链接存储结构的特点是指针表示逻辑关系。线性表的顺序存储结构是一种随机存取的存储结构,线性表的链接存储结构是一种顺序存取的存储结构。在长度为n顺序表中,等概率情况下,插入和删除一个元素平均需移动n/2、(n-1)/2个元素。若链表中最常用的操作是在最后一个结点之后插入一个结点和删除第一个结点,则采用带尾指针的单循环链表存储方法最节省时间;若链表中最常用的操作是在最后一个结点之后插入一个结点和删除最后一个
6、结点,则采用循环双链表存储方法最节省运算时间。对于n个元素组成的线性表,建立一个有序单链表的时间复杂度是O(n2)5 中缀后缀的相互转换(必考)典例:计算中缀表达 4+3*5,如何计算它的值。解答:第一步,将中缀转化为后缀,原则:1)遇到操作数,直接输出;2)栈为空时,遇到运算符,入栈;3)遇到左括号,将其入栈;4)遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;5)遇到其他运算符+-*/时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;6)最终将栈中的元素依次出栈,输出。第二步,计算后缀:435*+对后缀表达式从左到右进行扫描,遇到操作数据
7、,则压入栈;当遇到运算符时,就把其前面的两个操作数取出,进行运算;将运算结果再压入栈;直到计算出最终结果。中缀转前后缀快速方法:中缀式到其他式子的转换方法:a+b*c-(d+e) 1)按照运算符的优先级对所有的运算单位加括号:(a+(b*c)-(d+e)2)转前缀:把运算符号移动到对应的括号前面:-( +(a *(bc) +(de),把括号去掉:-+a*bc+de;3)后缀:把运算符号移动到对应的括号后面:(a(bc)* )+ (de)+ )- ,把括号去掉:abc*+de+- 栈通常采用的两种存储结构是顺序栈和链栈;其判定栈空的条件分别是top= -1,判定栈满的条件分别是top=NULL。
8、栈(LIFO)和队列(FIFO)是两种特殊的线性表,栈的操作特性是后进先出,队列的操作特性是先进先出,栈和队列的主要区别在于对插入和删除操作限定的位置不同。循环队列的引入是为了克服假溢出。数组Qn用来表示一个循环队列,front为队头元素的前一个位置,rear为队尾元素的位置,计算队列中元素个数的公式为(rear-front+n)% n。有n个元素依次进栈,则出栈序列有种。6 串的基本操作(代码)连接:是将主串和字符串s连接生成一个新的字符串public SeqString Concat(SeqString s) SeqString s1 = new SeqString(this.GetLen
9、gth() + s.GetLength(); for (int i = 0; i this.GetLength(); +i) s1.datai = thisi; for (int j = 0; s.GetLength(); +j) s1.datathis.GetLength() + j = sj; return s1;public SeqString Insert(int index, SeqString s) int len = s.GetLength(); int len2 = len + this.GetLength(); SeqString s1 = new SeqString(len
10、2); if (index this.GetLength() - 1) Console.WriteLine(Position is error!); return null; index; s1i = thisi; for (int i = index; index + len; s1i = si - index; for (int i = index + len; len2; s1i = thisi - len;7 矩阵转置的两种方式(过程)方法一:第一步:根据M矩阵的行数、列数和非零元总数确定N矩阵的列数、行数和非零元总数 。第二步:当三元组表非空(M矩阵的非零元不为0)时,对M中的每一列
11、col(0coln-1),通过从头至尾扫描三元组表data,找出所有列号等于col的那些三元组,将它们的行号和列号互换后依次放人N的data中,即可得到N的按行优先的压缩存贮表示 方法二:第一步,根据矩阵A计算矩阵B每一列非零元素个数cnum和每列第一个元素的起始位置cpot;第二步,将矩阵A中col列元素存放在B中下标为cpotcol的位置。(详见PPT chap06操作过程)8 二叉树的相关概念(选择)(11)满二叉树。(2)完全二叉树。满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。9 二叉树的性质(选择)性质1 一棵非空二叉树的第i层上最多有2i-1个结点(i1)。性质2 一棵
12、深度为k的二叉树中,最多具有2k1个结点。性质3 对于一棵非空的二叉树,如果叶子结点数为n0,度数为2的结点数为n2,则有: n0n21。性质4 具有n个结点的完全二叉树的深度k为log2n+1。性质5 对于具有n个结点的完全二叉树,如果按照从上至下和从左到右的顺序对二叉树中的所有结点从1开始顺序编号,则对于任意的序号为i的结点,有:(1)如果i1,则序号为i的结点的双亲结点的序号为i/2(“/”表示整除);如果i1,则序号为i的结点是根结点,无双亲结点。(2)如果2in,则序号为i的结点的左孩子结点的序号为2i;如果2in,则序号为i的结点无左孩子。(3)如果2i1n,则序号为i的结点的右孩
13、子结点的序号为2i1;如果2i1n,则序号为i的结点无右孩子。此外,若对二叉树的根结点从0开始编号,则相应的i号结点的双亲结点的编号为(i1)/2,左孩子的编号为2i1,右孩子的编号为2i2。10 二叉树的遍历(必考)前序: A、B、D、E、F、C,中序: D、B、E、F、A、C,求后序遍历分析:由前序得根节点为A,根据中序中A的位置可得DBEF构成左子树,C为右子树,如图a: 图 a 图 b同理,由前序B、D、E、F,得B为左子树的父节点,如图b;由中序D、B、E、F得D为左子树,E、F为右子树,如图c;图 c 图 d同理,可得到二叉树结构图,如图d:所以,后序遍历是:DFEBCA11 二叉
14、排序树(重要)在二叉树中,如果一个结点的左子结点的值永远小于该结点的值,而右子结点的值永远大于该结点的值,这样的二叉树为二叉搜索树。二叉排序树的建立过程就是结点插入的过程每次插入时必须从根结点开始,新插入点一定是叶子结点。12 哈夫曼树的构造(过程)4个叶结点,其权值分别为1,3,5,7,写出构造哈夫曼树的过程。(1)由给定的n个权值W1,W2,Wn构造n棵只有一个叶结点的二叉树,从而得到一个二叉树的集合FT1,T2,Tn;(2)在F中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和;(3)在集合F中删除作为左、右子
15、树的两棵二叉树,并将新建立的二叉树加入到集合F中;(4)重复(2)(3)两步,当F中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。13 双亲表示法与孩子链表表示法的相互转化(过程)双亲表示法:树中的结点除保存结点本身的信息之外,还要保存其双亲结点在数组中的位置(数组的序号)位置0 12345678910parent-1dataabcdefghijk1112131415161718192021lmnopqrst孩子链表表示法:结点除保存本身的信息外,不是保存其双亲结点在数组中的序号,而是保存一个链表的第一个结点的地址信息。这个链表是由该结点的所有孩子结点组成。每个孩子结点保存有两个信息,
16、一个是每个孩子结点在一维数组中的序号,另一个是下一个孩子结点的地址信息。14 树与二叉树的互转(过程)将树转换成二叉树加线:在兄弟之间加一连线.抹线:对每个结点,除了其左孩子外,去除其与其余孩子之间的关系.旋转:以树的根结点为轴心,将整树顺时针转45。将二叉树转换成树若p结点是双亲结点的左孩子,则将p的右孩子,右孩子的右孩子,沿分支找到的所有右孩子,都与p的双亲用线连起来 抹掉原二叉树中双亲与右孩子之间的连线调整:将结点按层次排列,形成树结构15 图的定义、分类(选择)图:由一系列顶点(结点)和描述顶点之间的关系边(弧)组成。有向图:在一个图中,如果任意两顶点构成的偶对(Vi,Vj)是有序的,
17、那么称该图为有向图。这里Vi是弧尾,Vj是弧头。这表示有一个从顶点Vi到顶点 Vj的路径。但是从Vj到Vi是不可能的。无向图:在一个图中,如果有任意两顶点构成的边(Vi,Vj),(Vi,Vj)和(Vj ,Vi)是相同的。无向完全图(完全图):在一个无向图中,任意两个顶点之间都有边相连,则称该图为无向完全图。有向完全图:在一个有向图,任意两个顶点之间都是弧相连。稀疏图:有很少条边或弧的图。稠密图:有很多条边或弧的图。16 图的两种遍历方式(必考)深度优先:从图的某一顶点x出发,访问x,然后遍历任何一个与x相邻的未被访问的顶点y,再遍历任何一个与y相邻的未被访问的顶点z,如此下去,直到到达一个所有
18、邻接点都被访问的顶点为止。然后依次回退到尚有邻接点未被访问过的顶点,重复上述过程,直到图中的全部顶点都被访问过为止。广度优先:从图的某个顶点x出发,访问x。然后访问与x相邻接的所有未被访问的顶点x1,x2,.,xn;接着再依次访问与x1,x2,.,xn相邻接的未被访问过的所有顶点。依此类推,直至图的每个顶点都被访问。(详见PPT chap09操作过程)17 排序算法(过程)快速排序:从待排序的n个记录中任意选取一个记录Ri(通常选取序列中的第一个记录)作标准,调整序列中各个记录的位置,使排在Ri前面的记录的关键字都小于Ri的关键字,排在Ri后面的记录的关键字都大于Ri的关键字,我们把这样一个过程称作一次快速排序。在第一次快速排序中,确定了所选取的记录Ri最终在序列中的排列位置,同时也把剩余的记录分成了两个子序列。对两个子序列分别进行快速排序,又确定了两个记录在序列中应处的位置,并将剩余的记录分成了四个子序列,如此重复下去,当各个子序列的长度为1时,全部记录排序完毕。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1