单链表的全翻转及固定半径翻转

有关链表的操作很多初学者总是望而却步,其实链表的操作关键在于指针的移动顺序,以及清楚理解需要保存的临时指针,理清思路即可。

这里演示了一个有关于单向链表的翻转示例,实现思路其实不难,但是真正写起来的时候回发现很多问题。

 

定义单链表结构体

1 typedef struct listnode
2 {
3     int value;
4     struct listnode *next;
5 } node;

 

全旋转单链表常规方法

 1 node *convert(node * head)
 2 {
 3     node * foreNode = NULL; // 当前结点的前一位
 4     node * nextNode = NULL; // 当前结点的后一位
 5     node * tempNode = NULL; // 当前结点,操作结点
 6     if(head == NULL || head->next == NULL)
 7         return head;
 8 
 9     nextNode = head->next;
10     tempNode = foreNode = head;
11     int i = 0;
12     while(nextNode != NULL)
13     {
14         head = nextNode;           // 更新链表头结点
15         nextNode = head->next;     // 更新下一次的头结点
16         tempNode->next = nextNode; // 更新目标链表末尾的结点指向
17         head -> next = foreNode;   // 头结点插入
18         foreNode = head;           // 头结点保存
19     }
20     return head;
21 
22 }

过程分析:示例单链表:1->2->3->4->5

1) 2->1->3->4->5

2) 3->2->1->4->5

3) 4->3->2->1->5

4) 5->4->3->2->1

 

全翻转单链表递归实现

1 node *reverse(node *head, node *pre)  // 作用:将pre连接到head的后面
2 {
3     node *p = head->next;
4     head->next = pre;
5     if(p)
6         return reverse(p, head);
7     else
8         return head;
9 }

 

以K为半径的单链表翻转

  示例:单链表为: 1->2->3->4->5->6->7->8,当K=3时,翻转输出 :3->2->1->6->5->4->7->8

  思路:由链表长度和翻转半径给链表进行分组,如8个结点、半径为3则分为2组,完整的2组内进行全翻转,不足半径长度的多余组不翻转,小组翻转完成后将组与组之间进行连接

 1 /// 以K为半径的单链表翻转
 2 node *convertWithK(node *head , int K)
 3 {
 4     node * tempNode = head;
 5     node * foreNode = head;
 6     node * nextNode = NULL; 
 7     node * foreEnd = NULL; // 用于保存前一组的末结点以便进行连接
 8     node * tempEnd = NULL;
 9 
10     if(!head || !head->next)
11         return head;
12     int i , j;
13 
14     // 计算需要移动的组
15     int count = 0;
16     while(tempNode)
17     {
18         count++;
19         tempNode = tempNode->next;
20     }
21     count = count / K;
22 
23     tempNode = head;
24     foreEnd = head;
25 
26     for(i = 0; i < count; i++) // 分组的循环
27     {
28 
29         tempEnd = tempNode; // 当前组翻转后的组末结点,及原组的组头结点
30         foreNode = tempNode; // 更新组首结点
31         tempNode = tempNode->next;  // 首位得向后移动一格
32         for(j = 0; j < K - 1; j++)
33         {
34             nextNode = tempNode->next;
35             tempNode->next = foreNode;
36             foreNode = tempNode;
37             tempNode = nextNode;
38         }
39 
40         // 连接与前一组的结点
41         if(i == 0)
42             head  = foreNode;  // 储存返回的头结点
43      // 非第一组的情况
44         if(i)          
45         {
46             foreEnd->next = foreNode;
47             foreEnd = tempEnd;
48         }
49 
50         // 连接与后一组的结点
51         if(i == count - 1)
52             tempEnd->next = tempNode;
53     }
54     return head;
55 } 

 至此单链表的翻转已完成,目测算法还不够简洁,复杂度有待优化,望大神指点!

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值