1.单链表逆序

实现1:

遍历:

/*
 * 遍历链表, 将每个结点的next置为其前驱
 * 遍历过程中需要额外的指针来记录结点的前驱和后继 
 */
   5: LinkList ReverseList(LinkList L)
   6: {
if (!L || !L->next) {
return L;
   9:     }
  10:  
  11:     Node *pre, *cur, *next;
  12:  
  13:     pre = next = NULL;
  14:     cur = L->next;
while (cur) {
  16:         next = cur->next;
  17:         cur->next = pre;
  18:         pre = cur;
  19:         cur = next;
  20:     }
  21:     L->next = pre;
  22:  
return L;
  24: }

实现2:

递归:

 

/* 
 * 采用递归,每次递归返回子链表反转后的头指针 
 */
   4: Node * ReverseList(Node *node)
   5: {
if (!node || !node->next) {
return node;
   8:     }
   9:  
  10:     Node *next = node->next;
  11:     Node *head = ReverseList(next);
  12:     next->next = node;
  13:     node->next = NULL;
  14:  
return head;
  16: }

2.合并有序链表

实现1:

遍历, 遍历两个链表,每次将较小的结点插入到合并后的新链表。

   1: Node *Merge(Node *head1, Node *head2)
   2: {
/* 如果一个链表为空, 则直接返回另一个 */
if (!head1) {
return head2;
   6:     }
if (!head2) {
return head1;
   9:     }
  10:     
/* head为合并后的头指针, p1 p2分别用来遍历两个链表 */
  12:     Node *head, *p1, *p2;
  13:     head = p1 = p2 = NULL;
if (head1->data < head2->data) {
  15:         head = head1;
  16:         p1 = head1->next;
  17:         p2 = head2;
else {
  19:         head = head2;
  20:         p2 = head2->next;
  21:         p1 = head1;
  22:     }
  23:     
/* cur为合并后链表的当前结点, 从p1和p2从选出较小的作为其后继 */
  25:     Node *cur = head;
while (!p1 && !p2) {
if (p1->data <= p2->data) {
  28:             cur->next = p1;
  29:             cur = p1;
  30:             p1 = p1->next;
else {
  32:             cur->next= p2;
  33:             cur = p2;
  34:             p2 = p2->next;
  35:         }
  36:     }
  37:     
/* 遍历完一个链表后,将另一链表剩余结点插入到新链表中 */
if (!p1) {
  40:         cur->next= p1;
else {
  42:         cur->next= p2;
  43:     }
  44:     
return head;    
  46: }

实现2:

递归,每次递归返回合并后新链表的头结点。

   1: Node *MergeRecursive(Node *head1, Node *head2)
   2: {
if (!head1 || !head2) {
return head1 ? head1 : head2;
   5:     }
   6:     
   7:     Node *head;
if (head1->data < head2->data) {
   9:         head = head1;
  10:         head->next = MergeRecursive(head1->next, head2);        
else {
  12:         head = head2;
  13:         head->next = MergeRecursive(head1, head2->next);
  14:     } 
  15:     
return head;
  17: }

3.判断两个无环单链表是否交叉,如果是则返回交点

实现1:

判断是否交叉:因为无环单链表只可能是Y型交叉,所以遍历两个链表至最后一个结点,判断最后一个结点是否相等即可。

bool IsCross(Node *head1, Node *head2)
   2: {
if (!head1 || !head2) {
return false;
   5:     }
   6:     
   7:     Node *p1 = head1;
   8:     Node *p2 = head2;    
while (p1->next) {
  10:         p1 = p1->next;
  11:     }
while (p2->next) {
  13:         p2 = p2->next;
  14:     }
  15:     
return (p1 == p2);
  17: }

找出交点:遍历两个链表,记录长度分别为L1和L2,先让长的链表向后移动abs(L1-L2),然后在逐个比较结点,第一个相等的结点即为交点。

   1: Node *FindCross(Node *head1, Node *head2)
   2: {
if (!head1 || !head2) {
return NULL;
   5:     }
   6:     
/* 求出两个链表的长度 */
   8:     Node *p1, *p2;
   9:     p1 = head1;
  10:     p2 = head2;
int len1, len2, len;
  12:     len1 = len2 = 0;    
while (p1) {
  14:         len1++;
  15:         p1 = p1->next;
  16:     } 
while (p2) {
  18:         len2++;
  19:         p2 = p2->next;
  20:     }
  21:     
/* 将长链表先移动len个结点 */
int i;
  24:     len = abs(len1 - len2);
  25:     p1 = head1;
  26:     p2 = head2;
if (len1 > len2) {
for (i = 0; i < len; ++i) {
  29:             p1 = p1->next;
  30:         }
else {
for (i = 0; i < len; ++i) {
  33:             p2 = p2->next;
  34:         }
  35:     }
  36:     
/* 遍历 找到第一个相等的结点即为交点 */    
while (!p1) {
  39:         p1 = p1->next;
  40:         p2 = p2->next;
if (p1 == p2) {
return p1;
  43:         }
  44:     }
  45:     
return NULL; 
  47: }

实现2:

将其中一个链表首尾相连,这样就转换成为判断另一个链表是否有环即求进入环的结点的问题。

4.判断单链表是否有环, 如果有环则返回进入环的第一个结点.

实现1:

设置快慢指针,初始都指向链表头,快指针每次前进两步,慢指针每次前进一步,如果有环则两个指针必定相遇。

判读是否有环:

bool HaveCircle(Node *head)
   2: {
if (!head) {
return false;
   5:     }
   6:     
   7:     Node *fast, *slow;
   8:     fast = slow = head;
   9:     
while (fast && fast->next) {        
  11:         slow = slow->next;
  12:         fast = fast->next->next;
if (fast == slow) {
return true;
  15:         }
  16:     }
  17:     
return false;
  19: }
找出环的位置:
实现2:

将结点的地址做hash,遍历链表,检测是否有地址相等的结点。

5.找出单链表的中间元素

实现:

设置快慢指针,初始都指向链表头,快指针每次前进两步,慢指针每次前进一步,当快指针到达链表末尾时,慢指针所指即为单链表的中间元素。

   1: Node *FindMid(Node *head)
   2: {
if (!head) {
return NULL;
   5:     }
   6:     
   7:     Node *fast, *slow;
   8:     fast = slow = head;
while (fast && fast->next) {
  10:         slow = slow->next;
  11:         fast = fast->next->next;
  12:     }
/* 如果是fast为NULL, 则链表长度为奇数, slow为中间结点
    *  如果是fast->next为NULL, 则链表长度为偶数, slow 和 slow->next 为中间结点 
    */    
return slow;
  17: }

6.删除单链表中倒数第k个结点

实现:

设置两个指针p1和p2,p1指向链表第一个结点,p2指向第k+1个结点,两个指针同时前进,当p2到达链表尾时,p1指向倒数第k+1个结点,删除p1后面的一个结点即可。

int k) {
if (!head) {
return NULL;
   4:     }
   5:     
int i;
   7:     Node *p1, *p2;
   8:     p1 = p2 = head;
for (i = 0; i <= k; ++i) {
if (p2) {
  11:             p2 = p2->next;
else {
return NULL;
  14:         }
  15:     }
  16:     
while (p2) {
  18:         p1 = p1->next;
  19:         p2 = p2->next;
  20:     }
  21:     p2 = p1->next;
  22:     p1->next = p2->next;
  23:     
return p2;    
  25: }

7.从单链表中删除指定的中间结点

实现:

将指定结点的后继的值赋值给指定结点,然后删除其后继即可。

void DeleteMidNode(Node *del)
   2: {
if (!del) {
return; 
   5:     }
   6:     
   7:     Node *next = del->next;
if (next) {
   9:         del->data= next->data;
  10:         del->next= next->next;
  11:         free(next);    
  12:     }
  13: }

8.在单链表的指定结点前插入一个结点

实现:

将结点插入到指定结点后,然后交换两节点的值即可。

int InsertBeforeNode(Node *node, Node *insert)
   2: {
if (!node || !insert) {
return -1;
   5:     }
   6:     
   7:     Node temp = *node;
   8:     node->data = insert->data;
   9:     node->next= insert;
  10:     *insert = temp;
  11:     
return 0;    
  13: }

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-08
  • 2022-12-23
  • 2021-09-06
猜你喜欢
  • 2021-09-06
  • 2021-06-26
  • 2021-09-27
  • 2022-02-14
  • 2021-10-19
  • 2022-02-09
相关资源
相似解决方案