数据结构中,链表的概念,无非是一个结构,或者类,自身中有一个Next属性或者叫任意的名字,但是类型必须也是这个节点的类型。比如下面的例子,类名叫node,其中也要有一个属性类型也是node,这样才能串接起来。如果有多个node属性的话,那可以实现双向链表,或者十字链表,树等多着结构
class node
{ public string content = "head"; public node next = null; public node() { } public node(string c) { content = c; } }
链表的增加元素方法,就是new一个节点,然后将这个节点赋值给链表的最后一个节点的next属性,或者更形象的说是next指向此节点。
如下代码:
node head = new node();
static void AppendNode(ref node head, node data)
{ node pointer= head; while (pointer.next != null) { pointer= pointer.next; } pointer.next = data; } 其中head是头结点。然后有一个指针pointer,它指向当前的节点,每当当前的节点的next属性值不是null,意味着当前节点后面还有节点,则pointer移动到下一个节点。直到pointer指向的当前节点后面是null,然后next属性赋值给新的节点。遍历和删除等操作可以参考数据结构的书,附件代码中也有。主要不要弄错指针指向的对象,和断开指针的顺序。
约瑟夫环的概念大家自己百度。
本文的实现方式,首先构造一个环形链表,收尾相连的。
static void CreateCycle(ref node head, int length)
{ node pointer = head; for (int i = 1; i <= length; i++) { node data = new node(i.ToString()); pointer.next = data; pointer = pointer.next; } pointer.next = head.next;//头尾相接。 }遍历这个环。
static void ShowCycle(node head)
{ node pointer = head; do { pointer = pointer.next; Console.Write(pointer.content + "->"); } while (pointer.next != head.next);//如果当前的指针的下一个元素是head的下一个元素,既可以断定所有的元素都遍历过了。 Console.WriteLine(); }最重要的方法是删除里面的元素,这里pointer一开始和head一样赋值,都指向第一个元素。此处有一些问题如果删除第一个元素,理论上,tobeDeletednode就是第一个元素,将它的值设置null,那么最尾的节点本来连接的tobeDeletednode,设成null后,最尾节点连接的就是null了。但是,测试下来,虽然tobeDeletednode设成null,但是并未真正的释放掉该元素,这和.net垃圾回收机制相关。因此不能用是否next的值为null来判断是否是环的最末元素,只能用是否元素的next指向的值和head指向的值是同一个,来判断是否为最末元素。应该可以有其他写法,但暂时未思考出。
而对于不是删除第一个元素,则很方便的用pointer定位,因此写出如下2中不同的实现,注意高亮的代码的逻辑都是一样的。删除完元素后,把head的next继续pointer指针的next,表示下轮从这个头开始。
//删除之后,head定位到下一个元素上
static void DeleteCycleNode(ref node head, int index)//index从1算起 { node pointer = new node("pointer"); pointer.next = head.next;//都指向第一个元素 node tobeDeletednode; if (index == 1)//如果删除的为第一个元素,pointer要定位到最后一个元素上 { do { pointer = pointer.next; } while (pointer.next != head.next);tobeDeletednode = pointer.next;
pointer.next = tobeDeletednode.next; head.next = pointer.next;//重新设定头指针 tobeDeletednode = null; } else { for (int i = 1; i < index; i++) { pointer = pointer.next; }tobeDeletednode = pointer.next;
pointer.next = tobeDeletednode.next; head.next = pointer.next;//重新设定头指针 tobeDeletednode = null; } } 最后调用一下,加上10元素的环,每次报到3的元素删除:head = new node();
CreateCycle(ref head, 10); ShowCycle(head); while (head.next.next != head.next)//如果头指向的元素的下一个元素是自己,那么表示这个环只剩下1个元素了,就退出while { DeleteCycleNode(ref head, 3); ShowCycle(head); }
结果如下: