单链表的递归与非递归实现

一:递归版本

 1 class LinkList
 2     {
 3         public class LinkNode
 4         {
 5             public int data;
 6
 7             public LinkNode next;
 8         }
 9
10         private LinkNode head;
11
12         public void Add(int data)
13         {
14             if (head == null)
15             {
16                 head = new LinkNode() { data = data };
17             }
18             else
19             {
20                 Add(head, data);
21             }
22         }
23
24         public void Add(LinkNode node, int data)
25         {
26             if (node.next == null)
27             {
28                 node.next = new LinkNode() { data = data };
29                 return;
30             }
31
32             Add(node.next, data);
33         }
34     }

二:非递归版本

 1    class LinkList
 2     {
 3         public class LinkNode
 4         {
 5             public int data;
 6
 7             public LinkNode next;
 8         }
 9
10         private LinkNode head;
11
12         public void Add(int data)
13         {
14             LinkNode node = new LinkNode() { data = data };
15
16             if (head == null)
17             {
18                 head = node;
19             }
20             else
21             {
22                 LinkNode temp = head;
23
24                 while (temp.next != null)
25                 {
26                     temp = temp.next;
27                 }
28
29                 temp.next = node;
30             }
31         }
32     }

这个非递归不理解的地方在于临时变量temp,提出的问题就是为什么:“temp.next=node” 之后,head的值发生了改变?我想之所以不能理解,绝逼是对

引用类型的内存分配不了解,而这个非递归版本恰恰就是用引用类型这个内存分配技巧来实现 ”非递归构建单链表“。。。为了不让别人踩上这个坑,我还是大

概说一下流程,大概是这样的,当我们在new一个引用类型的时候,CLR就要计算实例字段和所有基类上的实例字段的大小,然后再在堆上分配合理的内存块,

最后把堆上的内存块的首地址保存在栈上面。

为了方便理解,现在假如LinkList里面有三个结点:instance1 -> instance2 -> instance3,

第一句:

1 LinkNode temp = head;

这个句子不难理解吧,把head的地址赋给temp,那么栈上temp的地址也就是head的地址,head的地址就是指向instacnce1内存块地址。

第二句: 从这句while中可以看到,一直在找instance的next,可以看出之后把instance2的内存地址给了temp,再next之后就把instance3的内存地址给

了temp,然后就发现instance3的next为null,然后就跳出循环。

1                 while (temp.next != null)
2                 {
3                     temp = temp.next;
4                 }

第三句:从上一句可以看到,instance3的next已经为null了,这时候就把新构建的结点:LinkNode node = new LinkNode() { data = data };赋

给temp的next指针上来继续构建链表。

1 temp.next = node;

可以看到这时候instance4就构造到了instance3之后,同时temp.next已经是保存instance4的内存地址,这一些操作对head来说都是透明的,它也不管

后面怎么操作,当你遍历head的时候会惊奇的发现居然我的链表中多了一个instance4,这个也就是朋友疑惑的地方,如果看到这个内存分配图的话,

也许会豁然开朗,当然这篇博文没什么技术含量,也是自己一时有感而发。

http://www.cnblogs.com/huangxincheng/p/4025525.html

时间: 2024-10-11 23:05:22

单链表的递归与非递归实现的相关文章

单链表的合并(递归、非递归)

递归方法将两个链表合并成一个链表 例:已知两个单链表head1和head2各自有序升序排列,请把他们合并成一个连表并依然有序,并保留原来所有节点 假设以下两个链表: 链表1:1->3->5 链表2:2->4->6 (1)比较1和链表2的第一个节点数据,由于1<2,因此把结果链表头结点指向链表1中的第一个节点,即数据1所在的节点 (2)对剩余的链表1(3->5)和链表2在调用本过程,比较得到结果链表的第二个节点,即2与3比较得到2,此时合并后的链表节点为1->2,这

【算法题】使用递归和非递归实现单向链表的转置

在阅读的过程中有任何问题,欢迎一起交流 邮箱:[email protected] QQ:1494713801 问题: 给一个单向链表,把它从头到尾反转过来.比如: a -> b -> c ->d 反过来就是 d -> c -> b -> a . 分析: 假设每一个node的结构是: class Node { char value; Node next;} 非递归方式代码如下: 1. void reverse(struct Node **list) 2. { 3.    

链表反转的递归和非递归实现方式

链表反转是数据结构的基本功,主要有递归和非递归两种实现方式.我们一一介绍如下: 1. 非递归实现 主要包括如下4步: 1)如果head为空,或者只有head这一个节点,return head即可: 2)从头到尾遍历链表,把reversedHead赋值给当前节点的next: 3)当前节点赋值给reversedHead: 4)遍历结束,return reversedHead. 下图试图来辅助说明: 代码如下: node* reverseList(node* head) { if(head == NU

习题3.11 递归和非递归查找元素

//编写查找一个单链表特定元素的函数 递归 Position FindEle( ElementType X, List L ) { Position p; p = L->Next; if( p != NULL && p->Ele != X ) return FindEle(X,p); return p; } //非递归实现 Position FindEle( ElementType X, List L ) { Position p; p = L->Next; while(

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

JumpNode递归和非递归访问

JumpNode的定义结构为如下所示: struct JumpNode { int data; //存储数据 int order; // 记录访问次序,初始化均为0 JumpNode *jump, *next; // next为线性下一节点,jump为跳跃到下一节点 JumpNode(int d): data(d), order(-1), jump(NULL), next(NULL) {} }; 现在需要以递归和非递归的方式来访问到一个JumpNode *list.在访问的时候给各个节点的ord

简单迷宫算法(递归与非递归C++实现)

假定迷宫如下:1代表墙,0代表道路,起点在(1,1),终点(11,9)(PS:下标从0开始计算). 现在寻求一条路径能从起点到达终点(非最短). 有两种解法:递归与非递归. 递归算法思路: 要用递归,就要寻找一个子问题,该子问题是递归的.很明显,这道题的子问题就是从8个方向(上下左右还有四个斜角)中寻找一个可行方向并向前走一步,该子问题(seekPath函数)的实现代码如下: 1 struct offset{ 2 int x; 3 int y; 4 }; 5 offset move[8]={{-

二叉树之AVL树的平衡实现(递归与非递归)

这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八种情况对应平衡实现. [1] 情况1-2: 这种需要旋转的结构一般称之为LL型,需要右旋 (顺时针旋转). 我用一个图来抽象一下这两个情况,画的不好,我尽量表达吧. 此时需要对A进行平衡操作,方法为: 将A的左子树换为B的右子树. B的右子树换为A. 非递归实现的代码为: 1 void rotate

二叉树的广度优先遍历、深度优先遍历的递归和非递归实现方式

二叉树的遍历方式: 1.深度优先:递归,非递归实现方式 1)先序遍历:先访问根节点,再依次访问左子树和右子树 2)中序遍历:先访问左子树,再访问根节点吗,最后访问右子树 3)后序遍历:先访问左子树,再访问右子树,最后访问根节点 2.广度优先     按照树的深度,一层一层的访问树的节点 1 package Solution; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 import java.util.Stack; 6

二叉树三种遍历递归及非递归实现(Java)

import java.util.Stack; //二叉树三种遍历递归及非递归实现(Java) public class Traverse { /******************定义二叉树**************************/ private final int MAX_SIZE = 10; //链式存储 public static class BinaryTreeNode { int mValue; BinaryTreeNode mLeft; BinaryTreeNode