gavanwanggw

导航

单链表的各种操作 笔试 面试

一、链表与数组的 差别
1、逻辑结构   数组必须事先定义固定的长度  不能动态的增减   链表是动态分配内存
2、内存结构   数组从栈中分配空间   链表在堆中
3、数组在内存中顺序存储   链表随机存储    数组訪问效率高   链表插入删除方便
4、数组存在越界问题 


定义表头, 为方便操作 表头数据域为空
二、单链表插入 删除
bool insertList(List head, Type x, int index){


Node *p;
p = head;
int j = 1;
while(p->next&& j < index){
p = p->next;
++j;
}
if(p==NULL) return ERROR;
Node *tmp = (Node *)malloc(sizeof(Node));
tmp->data = x;
tmp->next = p->next; //tmp的后继指向原index位置的结点
p-next = tmp; //p的后继为新结点
return OK;
}
bool deleteList(List head, int index){
Node *p = head;
int j = 1;
while(p->next!=NULL&&j < i){
p = p->next;
++j;
}// p->next为第index个
if(p==NULL || p->next==NULL || j > i) return ERROR; //i可能为负值
Node *tmp = p->next; //tmp指向第index个
p->next = tmp->next; //第index+1个取代index
free(tmp);//释放空间
return OK;
}


三、找出单链表中的倒数第k个元素
解题思路
1、先遍历一遍 计算长度, 再找出后k个
2、双路齐下  p1从第一位開始,p2从第k为開始遍历  直到p2走到头
思路2代码:
Node* find(Node* head, int index){
Node *p1,*p2;
p1 = head;
p2 = head;
for(int i = 0; i < index; i++){ 
p2 = p2->next; //p2向后移k位
}
while(p2!=NULL){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}


四、单链表反转
解题思路:每次操作结点时  标注其前结点 后结点  对其进行操作
Node* reverse(Node *head){
Node *prev = NULL;
Node *pCur = head;
Node *rHead = NULL;


while(pCur!=NULL){
Node *pNext = head->next;
if(pNext == NULL)
    rHead = pCur;
pCur->next = prev; //改变顺序  当前结点指向 自己的前一个结点
prev = pCur; //当前结点变为前结点 (为了下一个结点准备)
pCur = pNext; //结点后移
}
}


五、从尾到头输出单链表
1、递归输出
2、非递归输出
非递归操作  : 
1).能够使用 “四” 的代码进行反转  然后输出
2).遍历结点入栈 然后输出


六、寻找单链表的中间结点
1、遍历求长度length  然后再遍历输出
2、双路齐下   p1走一步 p2走两步 p2走到终点时 p1正好到中点
Node* findMiddle(Node *head){
Node *p1 = head;
Node *p2 = head;
while(p2->next->next!=NULL){
p2 = p2->next->next;
p1 = p1->next;
}
return p1;
}
七、单链表排序
与数组排序差别不大。交换元素时 仅仅交换数据域的内容就好。链表的顺序结构不用变化


八、单链表中随意 交换两个元素 (要注意表头)
将2个结点进行交换 要注意 next指针的 交换问题
//将p q结点交换
Node* swap(Node* head,Node* p,Node* q){
if(head==NULL || p==NULL ||  q==NULL){
Print(ERROR);
return head;
}
if(p==q){
Print(OK);
return head;
}
else if(p->next == q){ //两节点相邻
Node* prev = getPrev(p);
p->next = q->next;
q->next = p;
prev->next = q;
}
else if(q->next == p){
Node* prev = getPrev(q);
q->next = p->next;
p->next = q;
prev->next = p;
}
else if(p!=q){ //两节点不相邻 且不同  交换前后指针域
Node* prev1 = getPrev(p);
Node* prev2 = getPrev(q);
Node* next1 = p->next;
Node* next2 = q->next;
p->next = next2;
prev2->next = p;
q->next = next1;
prev1->next = q;
}
return head;
}




九、检測一个较大的单链表是否有环
双路齐下法  一个走一步一个走2步 看是否会相遇


十、推断两个(无环)单链表是否交叉
推断最后一个结点是否同样


十一、删除单链表中的反复结点
哈希, 建议一hash_map ,遍历链表 若结点出现反复则删除


十二、合并两个有序链表(非交叉)
1、递归
Node* Merge(Node* head1, Node* head2){
if(head1==NULL)
return head2;
if(head2==NULL)
return head1;
Node* head=NULL;
if(head1->data < head2->data){
head = head1;
head->next = Merge(head1, head2);
}else {
head = head2;
head->next = Merge(head1, head2);
}
return head;
}
2、非递归
Node* Merge(Node*head , Node* head1, Node* head2){
Node* tmp = head;
while(head1!=NULL&&head2!=NULL){
if(head1->data < head2->data){ 
tmp->next = head1;//指向head1当前结点
tmp = head1;//移动tmp的位置
head1 = head1->next;//head1后移
}else {
tmp->next = head2;
tmp = head2;
head2= head2->next;
}
}
if(head1==NULL)
tmp->next = head2;
if(head2==NULL)
tmp->next = head1;
return head;
}

posted on 2017-06-10 17:47  gavanwanggw  阅读(149)  评论(0编辑  收藏  举报