2双向链表表循环链表有序链表的常见操作.docx
- 文档编号:3729467
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:13
- 大小:17.38KB
2双向链表表循环链表有序链表的常见操作.docx
《2双向链表表循环链表有序链表的常见操作.docx》由会员分享,可在线阅读,更多相关《2双向链表表循环链表有序链表的常见操作.docx(13页珍藏版)》请在冰豆网上搜索。
2双向链表表循环链表有序链表的常见操作
数据结构面试之二——双向链表表、循环链表、有序链表的常见操作
题注:
《面试宝典》有相关习题,但思路相对不清晰,排版有错误,作者对此参考相关书籍和自己观点进行了重写,供大家参考。
二、双向链表
双向链表的建立是在单链表的基础上,多了一个指向前驱的指针back。
其他的操作类似,注意点就是在双向链表的操作,尤其插入、删除操作中需要修改两个指针的指向,一个是back指针,一个是next指针。
1.双向链表的构建【前面插入】
构建双向链表注意点:
1)修改first指针(头指针)的指向。
2)修改back、next指针。
//反向表头插入,从前面插入...
template
nodeType
:
buildListBackward()
{
nodeType
intnum;
cout<<"Enteralistofintegerendwith-999."< cin>>num; while(num! =-999) { //..add newNode=newnodeType newNode->info=num; newNode->next=NULL; newNode->back=NULL; if(first==NULL) { first=newNode; } else { newNode->next=first; first->back=newNode; first=newNode; } cin>>num; } returnfirst; } 2.双向链表的插入节点【此处考虑插入后保证有序,直接插入排序】 节点的插入同单链表,依然需要考虑多种因素。 分以下几类: 1)双向链表为空,“提示信息”并返回。 2)双向链表非空,待插入节点的元素值小于first节点,需要修改first指针。 3)双向链表非空,待插入节点的元素值为链表中间的节点,需修改back、next指向。 4)双向链表非空,待插入节点在最末尾节点以后,修改最末节点的指针。 //双向不循环链表 template voiddoublyLinkedList : insertNode(constType&insertItem)//new { nodeType nodeType nodeType boolfound=false; newNode=newnodeType newNode->info=insertItem; newNode->next=NULL; newNode->back=NULL; //case1: 空表 if(first==NULL) { first=newNode; } else { current=first; while(current! =NULL) { if(current->info>=insertItem) { found=true; break; } else { trailCurrent=current; current=current->next; } } //case2: 第一个节点 if(current==first) { current->next=newNode; newNode->back=current; } else { //case3: 中间节点 if(current! =NULL) { newNode->next=trailCurrent->next; current->back=newNode; trailCurrent->next=newNode; newNode->back=trailCurrent; } else//case4: 最后一个节点前 { trailCurrent->next=newNode; newNode->back=trailCurrent; }//endcase4 } } } 3.双向链表的删除节点 同样需要考虑以下几点: 1) 链表为空,“提示信息”并返回。 2) 链表非空,查找删除的元素在链表是否存在。 是的话,found=true;否的话,found=false。 3) 如果没有找到包含查找元素的节点,“错误提示”并返回。 4) 如果找到,主要节点位置。 如果是头节点或末尾节点主要修改first指针,及节点的back、next指向;如果不是头节点或者末尾节点就是中间节点,主要back、next的指向,完成插入。 template voiddoublyLinkedList : deleteNode(constType&deleteItem)//new { nodeType nodeType boolfound=false; //case1: 空表 if(first==NULL) { cout<<"TheListisNULL! "< exit (1); } else { current=first; while(current! =NULL) { if(current->info==deleteItem) { found=true; break; } else { trailCurrent=current; current=current->next; } } if(found) { //case2: 第一个节点 if(current==first) { first=current->next; deletecurrent; } else { //case3: 中间节点 if(current! =NULL) { if(current->next! =NULL)//case3.1: 要删除的是中间节点. { trailCurrent->next=current->next; current->next->back=trailCurrent; deletecurrent; } else { trailCurrent->next=NULL;//case3.2: 要删除的为最后一个节点. deletecurrent; } } }//endelse }//endif else { cout<<"Theelem"< "< 链表中无此节点. } }//endelse }//end 三、循环链表 循环链表能保障从每一个节点出发都能检索链表。 即: last指针的指向不再为空,而是指向了first(头结点)。 循环链表在构建链表、查找元素、插入、删除、操作中要注意修改末尾节点指针的指向,保证链表的循环。 1. 前插式构建循环链表 【思路】: 每次在first指针前面插入节点;插入每个节点后注意修改last->link的指向。 template voidcycleList : bulidCycListBackward()//前插构造循环链表. { TypenewItem; while(cin>>newItem,newItem! =-999) { nodeType newNode->info=newItem; newNode->link=NULL; if(first==NULL) { first=newNode; last=newNode; first->link=first; last->link=first; } else { newNode->link=first; last->link=newNode; first=newNode; } } cout<<"输入完毕! "< } 2. 循环链表插入元素[后插入] 【思路】: 同构造循环链表,每次在last指针后面插入节点;插入每个节点后注意修改last->link的指向。 //只在last末尾插入 template voidcycleList : insertCycList(constType&newItem) { nodeType newNode->info=newItem; newNode->link=NULL; if(first==NULL)//链表为空... { first=newNode; last=newNode; first->link=first; last->link=first; } else//链表非空... { last->link=newNode; newNode->link=first; last=newNode; } cout< "< } 3. 删除循环链表节点 考虑到是否为空链表、删除元素在链表中不存在、及节点存在(节点的位置可能为共分头、中间、尾),所以分为以下5种情况分别处理。 : //case1: 链表为空。 //case2: 链表非空,删除节点为头节点。 //case3: 链表非空,删除节点为尾节点。 //case4: 链表非空,删除节点为中间节点。 //case5: 链表非空,不存在=deleteItem的节点。 template voidcycleList : delCycList(constType&deleteItem) { nodeType nodeType nodeType boolfound=false; if(first==NULL) { cout<<"TheListisEmpty! "< return; } if(first->info==deleteItem)//case2 { temp=newnodeType temp=first; first=first->link; last->link=first; cout<<"Thenodehas"< "< deletetemp; return; } else//cas3,case4.需要查找后定位。 { current=first->link; while(! found&¤t! =first) { if(current->info==deleteItem) { found=true; break; } else { trailCurrent=current; current=current->link; } }//endwhile if(found) { temp=newnodeType if(current==last)//case3 { temp=last; trailCurrent->link=last->link;//last->link=first last=trailCurrent; } else { temp=current; trailCurrent->link=current->link; } cout<<"TheElem: "< "< deletetemp; } else { cout<<"TheElem: "< "< } }//endelse } 四、有序链表 注意: 此处有序链表无非是在之前的一、单链表的操作的基础上,在插入元素的时候,按顺序插入,考虑的排序。 为了体现有序的特点,特通过递归实现了有序链表的逆序打印。 关于有序链表或者链表的非递归实现,可以通过栈实现。 下一节会分析并实现。 1. 有序链表的插入 考虑以下三种情况: 1) 当前链表为空; 2) 当前链表非空,要插入的元素值小于头结点的元素值; 3) 当前链表非空,要插入的元素值大于头结点的元素值,可以考虑找到第一个大于其的元素则停止搜索,插入其前即可。 template voidorderedLinkedListType : insertNode(constType&newItem) { nodeType nodeType nodeType boolfound=false; newNode=newnodeType newNode->info=newItem; newNode->link=NULL; if(first==NULL)//case1: 链表为空. { first=newNode; last=first; } else { current=first; while(! found&¤t! =NULL)//循环查找 { if(current->info>=newItem) { found=true; break; } else { trailCurrent=current; current=current->link; } }//endwhile //first特殊处理.. if(current==first)//case2: 新插入的元素小于first节点的元素值.. { newNode->link=first; first=newNode; } else//其他.. { newNode->link=current;//case3: 新插入的节点在非first位置 trailCurrent->link=newNode; } }//endelse } 2. 递归实现有序链表的逆序打印 template voidorderedLinkedListType : printListReverse()const//逆序打印. { reversePrint(first); cout< } //递归实现单链表的逆序打印. template voidorderedLinkedListType : reversePrint(nodeType { if(current! =NULL) { reversePrint(current->link); cout< } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 双向 表表 循环 有序 常见 操作