链表问题

来源:互联网 发布:网络诈骗 运营商 编辑:程序博客网 时间:2024/05/16 06:27

关于链表插入和删除的注意事项:
1.特殊处理链表为空和链表长度为1的情况。
2.注意插入操作调整的过程
3.注意头尾节点需要特殊考虑

给定一个整数num,在有序环形链表中插入一个节点值为num的节点,并且保证这个环形单链表依然有序。

采用两个节点指针,判断何种情况需要在两个指针之间插入节点。如果两个指针转了一圈都没有发现要插入的位置,则插在头结点前

给定一个链表的头结点head,在给定一个数num,把链表调整成节点值小于num的节点都放在链表值等于num的放在链表的中间,链表值大于num的节点放在链表的右边

方法一:
1.将链表的所有节点都放在数组中,然后将数组进行快排划分调整过程。
2.将数组重新连成链表

方法二:
分别将小于部分,等于部分,大于部分形成三个小链表,再将三个小链表连成大链表

给定两个有序链表的头结点,h1和h2打印两个有序链表的公共部分。

如有有一个为空,直接返回
否则,分别从两个链表的头结点遍历,如果n1

设计一个单链表函数,给定一个链表的头节点,使每k个节点之间逆序,如果最后不够k个节点,则不调整。

方法一:
利用栈进行处理,元素依次进栈,进够k个就依次弹出,如果最后不足k个则不要逆序
方法二:
记录下每组节点的头节点,每收集k个元素进行逆序调整,

给定一个单链表的头结点,再给定一个val,把所有等于val的节点删掉

可以看最构造新链表的过程。

一个链表中,每个节点不仅含有一条指向下一个节点额next指针,同时含有一条rand指针,rand指针可能指向任何一个链表中的节点,请复制这种含有rand指针节点的链表。

把每一个节点的拷贝节点放到原节点的后面。

1.单链表的创建、测长、节点查找、删除、插入、打印、反转

这里写图片描述

链表的反转
为了反转这个单链表,我们先让头结点的next域指向结点2,再让结点1的next域指向结点3,最后将结点2的next域指向结点1,就完成了第一次交换,顺序就变成了Header-结点2-结点1-结点3-结点4-NULL,然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转,思路有了,就该写代码了:

//将1,2节点交换,//head ->next =  node2;//node1 ->next = node2->next;//node2 ->next = node1;Node *Reverse_List(Node *head){    Node *rev_head = NULL;    Node *pNode = pHead;    Node *pPrev = NULL;    while(pNode != NULL){        Node *pNext = pNode ->next;        if(pNode)            rev_head = pNode;        pNode ->next = pPrev;        pPrev = pNode;        pNode = pNext;    }     return rev_head;}

2.双向链表的创建、测长、节点查找、删除、插入、打印、反转

3.不使用缓冲区移除链表中重复的节点

4.编写算法找出单链表中倒数第k个节点

利用快指针慢指针来实现:
两个指针指向头节点,快指针先向前走k-1步,然后两个指针再一起移动,最后快指针到达链表末尾的时候慢指针指向倒数第k个节点。

void FindKthtoTail(Node *head, int k ){    if(NULL == head || 0 == k)        return;    Node * quick = head;    Node* slow  =NULL;    for(size_t  i = 0; i< k-1 ;++i){  //快指针先走k-1步        if(quick ->next ){            quick = quick->next ;    }    slow = head;    while(quick ->next){  //快慢指针同时前进        quick = quick-<next;         slow = slow->next;   }  cout<<slow->data<<endl;    return ;    }

5.删除单链表中某个节点,且只能访问该节点

6.以给定值x为基准,将链表分割成两部分,所有小于x的节点排在x之前

7.两个链表表示两个整数,每个节点表示整数的一位,数位反向(正向)存放,以链表的形式返回两个数的和——大整数问题

8.编写一个方法,传入一个有环链表,返回环路的头结点。如果无环则返回NULL

利用hash表来实现,遍历每个节点,直到出现一个重复出现的节点
方法二:利用快指针、慢指针:若有环,则两个指针会在链表中的某个位置相遇,此时快指针从头重新遍历,当再次相遇的时候,就都指向环头。

9.编写一个方法,判断链表是否是回文串

10.寻找单链表中的中间元素

11.单链表的正向排序

12.判断链表是否存在环

13.有序单链表的合并

Node *Merge(Node *head1,Node *head2){    if(head1 == NULL)        return head2;    else if(head2 == NULL)        return head1;    Node *merged_head = NULL;    if(head1->data < head2->data){        merged_head = head1;        merged_head - >next  =Merge(head1->,head2)    }    else {        merged_head = head2;        merge_head ->next = Merge(head1,head2->next);    }    return merged_head;}

14.约瑟夫环问题

15.有序双向循环链表的插入

16.删除两个双向循环链表的相同节点

17.反向打印链表

利用栈、递归来实现

void Reverse_PrintList(Node *head){    stack<Node*> nodes;    Node *pNode = head;    while(pNode != NULL){        nodes.push(pNode);        pNode = pNode->next;    }    while(!nodes.empty()){        pNode = nodes.top();        nodes.pop();        cout<< pNode -> data<<endl;    }}//利用递归来实现void reverse_PrintList(Node *head){    if(head){        reverse_PrintList(head->next);        cout<<head->data<<endl;    }    return ;}

18.单链表反转的递归实现

19.复杂链表的复制

20.求两个链表的第一个公共子节点

两个链表从后到前寻找,找到最后一个相同的节点就是两个链表的第一个公共子节点,使用两个辅助栈。
Tips:该题在逆时针旋转90度之后编程寻找最低公共祖先的问题。

21.二叉搜索树和双向链表:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,不能创建任何新节点,只能调整树中节点指针的指向。

解法:中序遍历的过程中,将前驱和后继连接起来

void change(Node *p, Node *&last) //中序遍历{ if (!p)  return; change(p->left, last); if (last)  last->right = p; p->left = last; last = p; change(p->right, last);}void main(){ Node *root = create(); Node *tail = NULL; change(root, tail); while (tail) {  cout << tail->data << " ";  tail = tail->left; } cout << endl;}

22.圆圈中最后剩下的数字:0,1,…,n-1 这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字

给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。

如果不带环:

我们只要判断俩个链表的尾指针是否相等。
相等,则链表相交;否则,链表不相交。

1.先判断带不带环
2.如果都不带环,就判断尾节点是否相等
3.如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。
如果在,则相交,如果不在,则不相交。

0 0