考研网上

核算机考研和公司面试要点--表介绍(Java完成链表的数组和链表标明...

后台-系统设置-扩展变量-手机广告位-内容正文顶部


链表的介绍
1.表中的结点呈现次序摆放,归于线性数据规划,就像一列火车相同,每一节车厢恰当于表上的一个结点。
2.在表中其时结点之前的结点称为前驱,之后的结点为后继。
3.当表中没有元素时,也就是表元素个数为0,此时表为空表

表的数组完成
界说表
运用数组完成一个最简略的表规划,只是包括添加元素、批改元素、查找元素和删去元素,以及当数组容量不可时的扩容操作。在表中界说三个变量,表中数组的初始化巨细,表中其时元素个数,和一个object数组用于装载元素,因为java数组是协变的,不撑持泛型的运用,这儿咱们用object初始化数组,之后强行类型转化。

private int occupation = 3;//界说表初始化长度为3
private int size = 0;//初始化0个元素
private object[] elements = new object[occupation];//java数组是协变的,不撑持泛型数组,这儿用object数组

添加元素
数组完成表的添加元素操作分两种,一种是添加元素到指定的索引方位,另一种是直接添加元素在表的结束。关于扩容之后再说,假定数组容量足够的情况下,添加元素操作分两步进行:


step1.索引之后的元素顺次后移一位
step2.在索引出刺进数据,表的巨细添加1

public e addelement(e ele){
while (size >= occupation){
resize();//扩容
}
elements[size++] = ele;//step1.结束之后没有元素需要移动; step2.刺进元素
return ele;
}
public e addelement(e ele, int index){
if (index >= occupation){
return null;//没有对应的结点方位
}
while (size >= occupation){
resize();//扩容
}
for (int i = size; i > index; i--){//step1.索引之后的元素顺次后移一位
elements[i] = elements[i - 1];
}
elements[index] = ele;//step2.在索引出刺进数据
size++;//step2.表的巨细添加1
return ele;
}

批改元素
根据索引定位元素,批改数据。

public e modifyelement(e ele, int index){
if (index >= size || size == 0){
return null;
}
elements[index] = ele;
return ele;
}

查找元素
数组完成表规划分两种情况,第一种根据索引在数组中直接定位元素回来;第二种首要查找元素地址方位,查找成功回来成果。

public e getelement(int index){
if (index >= size || size == 0){
return null;
}
return (e)elements[index];//根据索引在数组中直接定位元素回来
}
public e getelement(e ele){
int index = -1;
for (int i = 0; i < size; i++){//查找元素地址方位
if (ele.equals((e)elements[i])){
index = i;
break;
}
}
if (-1 != index){//查找成功回来成果
return (e)elements[index];
}
return null;
}

删去元素
数组完成的表删去元素操作与添加元素操作刚好相反。添加操作是先后移再刺进,删去操作则是先取出再前移。删去元素操作相同分两步进行:


step0.假定函数传入元素,则首要需要定位元素地址索引
step1.取出元素,表的巨细减1
step2.索引之后的元素顺次前移一位

public e delelement(int index){
if (index >= size || size == 0){
return null;
}
object ele = elements[index];//取出元素
size--;//表的巨细减1
for (int i = index; i < size; i++){//索引之后的元素顺次前移一位
elements[i] = elements[i + 1];
}
return (e)ele;
}
public e delelement(e ele){
int index = -1;
for (int i = 0; i < size; i++){//查找索引
if (ele.equals((e)elements[i])){
index = i;
break;
}
}
if (-1 != index){
return delelement(index);//取出元素,表的巨细减1,索引之后的元素顺次前移一位
}
return null;
}

扩容
扩容函数是在初始数组容量不可时刺进元素所引发的操作,将原有的数组巨细扩展,在这儿咱们把数组容量每次扩展到正本的2倍巨细,而且运用arrays.copyof()函数把原有元素仿制到新的扩容之后的数组中。

private void resize(){
occupation = occupation * 2;
elements = arrays.copyof(elements, occupation);
}

表的链表完成
界说结点
这儿运用单向链表规划完成表,每个结点都具有指向下一个结点的引证next,最终一个结点next为null。而且链表具有头结点,头结点不代表任何元素,其next指向链表的第一个元素;为了遍历刺进元素便利界说last指向链表的最终一个结点;界说size字段标明链表其时结点个数。

private int size = 0;
private mylinkedlistnode<e> head = new mylinkedlistnode<e>(null, null);//头指针,用于标明链表,不标明元素
private mylinkedlistnode<e> last = null;

//链表结点的界说
private class mylinkedlistnode<e>{
private e e;
private mylinkedlistnode<e> next;
mylinkedlistnode(e e, mylinkedlistnode next) {
this.e = e;
this.next = next;
}
}

添加元素
因为存在last引证指向链表最终一个元素,因而在链表结束刺进元素很简略,在last后直接刺进元素。仅有留心的就是空表是需要直接操作head头结点,而且赋值last引证。

public e addelement(e ele){
if (null == head.next){//当链表为空时,在头结点之后直接刺进元素
head.next = new mylinkedlistnode<e>(ele, null);
last = head.next;//更新last引证指向链表最终一个元素
size++;//链表巨细加1
return ele;
}
last.next = new mylinkedlistnode<e>(ele, null);//假定非空链表,在last后直接刺进元素,即链表的结束
last = last.next;//last更新
size++;//链表巨细加1
return ele;
}

与数组标明不一样之处在于链表不能经过索引直接定位要刺进的方位


step1.需要根据索引index先定位到即将刺进到当地
step2.再操作链表的next引证。

public e addelement(int index, e ele){
if (index > size){//index可以等于size,标明将元素刺进到链表的结束
return null;
}
mylinkedlistnode<e> f = head;
for (int i = 0; i < index; i++){//step1.根据索引index先定位到即将刺进到当地
f = f.next;
}//循环结束f为要刺进元素的前一个方位,即index-1
mylinkedlistnode<e> cur = new mylinkedlistnode<e>(ele, null);//生成新结点
cur.next = f.next;//新结点next指向f的next
f.next = cur;//f结点next指向新结点,这样新结点就现已刺进到index方位上
size++;//链表巨细加1
return ele;
}

批改元素
定位结点与之前添加操作不一样,添加操作是找到索引的前一个方位(index - 1),而批改需要定位索引方位(index)


step1.定位索引index的结点
step2.批改结点的值

public e modifyelement(int index, e ele){
if (index >= size){
return null;
}
mylinkedlistnode<e> f = head;
for (int i = 0; i < index + 1; i++){//定位索引index的结点
f = f.next;
}//循环结束后,f结点就是索引index的方位
f.e = ele;//批改结点的值
return ele;
}

查找元素
链表根据索引查找元素从头节点往后递加遍历元素直到抵达索引index方位

public e getelement(int index){
if (index >= size){
return null;
}
mylinkedlistnode<e> f = head;
for (int i = 0; i < index + 1; i++){//链表查找元素从头节点往后递加遍历元素
f = f.next;
}//循环结束抵达索引index方位
return f.e;
}

链表根据元素查找,从头节点往后遍历一切结点直到找到中止,假定最终没有找到回来null。

public e getelement(e ele){
mylinkedlistnode<e> f = head;
for (int i = 0; i < size; i++){//从头节点往后遍历一切结点直到找到中止
f = f.next;
if (ele.equals(f.e)){
return ele;
}
}
return null;//假定最终没有找到回来null
}

删去元素
根据索引删去元素


step1.定位元素前一个索引方位(index-1),即删去结点的前驱
step2.操作指针,将删去结点前驱next指针指向删去结点的后继

public e delelement(int index){
if (index >= size){
return null;
}
mylinkedlistnode<e> f = head;
for (int i = 0; i < index; i++){//定位删去结点的前驱
f = f.next;
}//循环结束f为删去结点的前驱
mylinkedlistnode<e> del = f.next;
f.next = f.next.next;//操作指针,将删去结点前驱指针指向删去结点的后继
size--;
return del.e;
}

根据元素直接删去逻辑中,咱们添加pre引证用于在遍历中时刻指向f引证的前驱,pre和f顺次后移遍历链表的结点直到f找到要删去的结点中止,或许f为null时证明现已遍历到链表结束没有找到元素。假定找到即将删去的元素,pre引证的next指向f.next指向的结点,f.next置null,这样删去的结点f就被删去了。

public e del

element(e ele){
mylinkedlistnode<e> pre = head;//pre引证用于在遍历中时刻指向f引证的前驱
mylinkedlistnode<e> f = head.next;
for (int i = 0; i < size; i++){//pre和f顺次后移遍历链表的结点
if (ele.equals(f.e)){//找到即将删去的元素
break;
}
f = f.next;
pre = pre.next;
}
if (null != f){//f不为null,找到即将删去的元素
pre.next = f.next;//pre引证的next指向f.next指向的结点
f.next = null;//f.next置null
size--;//链表巨细减1
return f.e;
}
return null;//f为null时,证明遍历整个链表没有找到元素
}

总结
使用数组和单向链表简略地完成数据规划表,而且供给根柢的增批改查操作,这些操作都是表的最根柢的完成。但只是这些操作并缺乏以应对往常的出产需要,表规划的操作还大约包括更多,例如判别是不是为空表,表的最大巨细设定(在咱们比方中可以向表中无限添加元素直到内存耗尽中止,假定有胸怀叵测的人向表中歹意添加元素将致使咱们隙Ю溃)等等;在多线程环境中还需要思考并发时数据的共同性等疑问;单向链表完成具有捆绑性,假定寻找某个结点的前驱在没有特别的辅佐方案时需要从头再遍历一遍链表。所幸java的api供给了表的完成arraylist和linkedlist(双向链表完成),具有更完善的操作;java.util.concurrent供给多线程环境下的笼统数据规划。

有关算法例题
链表标明的两数相加
删去链表的倒数第n个结点
兼并两个有序链表
兼并k个有序链表
两两交流链表中的节点
k个一组翻转链表
链表每个节点向右循环移动 k 个方位

未经允许不得转载:考研网上 - 考研网上辅导班有用吗 > 核算机考研和公司面试要点--表介绍(Java完成链表的数组和链表标明...

后台-系统设置-扩展变量-手机广告位-内容正文底部

相关推荐

评论

留言与评论(共有 0 条评论)
   
验证码: