您的位置:首页 > 职场人生

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

2017-06-10 17:47 417 查看
一、链表与数组的 差别

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: