线性表 - 双链表
2011-08-13 16:26 DylanChan 阅读(221) 评论(0) 编辑 收藏 举报双向链表(double linked list):在单链表的每个结点中,再设置一个指向其前驱结点的指针域
01 | /// <summary> |
02 | /// 定义双向链表结点类 |
03 | /// </summary> |
04 | public sealed class DoubleLinkedListNode<t> |
05 | { |
06 | //存放数据 |
07 | private T tData; |
08 | //后继结点 |
09 | private DoubleLinkedListNode<t> nNext; |
10 | //前继结点 |
11 | private DoubleLinkedListNode<t> nPrev; |
12 |
13 | public T Data |
14 | { |
15 | get { return this .tData; } |
16 | set { this .tData = value; } |
17 | } |
18 | public DoubleLinkedListNode<t> Next |
19 | { |
20 | get { return this .nNext; } |
21 | set { nNext = value; } |
22 | } |
23 | public DoubleLinkedListNode<t> Prev |
24 | { |
25 | get { return this .nPrev; } |
26 | set { nPrev = value; } |
27 | } |
28 |
29 | public DoubleLinkedListNode(T data, DoubleLinkedListNode<t> next, DoubleLinkedListNode<t> prev) |
30 | { |
31 | this .tData = data; |
32 | this .nNext = next; |
33 | this .nPrev = prev; |
34 | } |
35 |
36 | public DoubleLinkedListNode() |
37 | : this ( default (T), null , null ) |
38 | { } |
39 |
40 | public DoubleLinkedListNode(T data) |
41 | : this (data, null , null ) |
42 | { } |
43 | } |
001 | /// <summary> |
002 | /// 定义双向链表类(带头结点) |
003 | /// </summary> |
004 | public sealed class DoubleLinkedList<t> |
005 | { |
006 | //定义头结点 |
007 | private DoubleLinkedListNode<t> nHead; |
008 | public DoubleLinkedListNode<t> Head |
009 | { |
010 | get { return this .nHead; } |
011 | set { nHead = value; } |
012 | } |
013 |
014 | /// <summary> |
015 | /// 初始化带头结点的空表 |
016 | /// </summary> |
017 | public DoubleLinkedList() |
018 | { |
019 | this .nHead = new DoubleLinkedListNode<t>(); |
020 | } |
021 |
022 | /// <summary> |
023 | /// 实现索引 |
024 | /// </summary> |
025 | public T this [ int index] |
026 | { |
027 | get { return GetElement(index + 1); } |
028 | } |
029 |
030 | /// <summary> |
031 | /// 获取链表长度 |
032 | /// </summary> |
033 | /// <returns>返回表长</returns> |
034 | public int Count() |
035 | { |
036 | int result = 0; |
037 | //指向头结点 |
038 | DoubleLinkedListNode<t> listNode = this .nHead; |
039 | while (listNode.Next != null ) |
040 | { |
041 | result++; |
042 | //移动指针,指向下一结点 |
043 | listNode = listNode.Next; |
044 | } |
045 | return result; |
046 | } |
047 |
048 | /// <summary> |
049 | /// 判断链表是否为空 |
050 | /// </summary> |
051 | /// <returns>true, 链表为空</returns> |
052 | public bool IsEmpty() |
053 | { |
054 | return this .nHead.Next == null ; |
055 | } |
056 |
057 | /// <summary> |
058 | /// 清空链表 |
059 | /// </summary> |
060 | public void Clear() |
061 | { |
062 | //第一结点设为NUll,所有后继结点由于失去引用,等待GC自动回收 |
063 | this .nHead.Next = null ; |
064 | } |
065 |
066 | /// <summary> |
067 | /// 获取指定位置的元素 |
068 | /// </summary> |
069 | /// <param name="i">链表位置 |
070 | /// <returns>返回链表的元素</returns> |
071 | public T GetElement( int i) |
072 | { |
073 | //链表为空 |
074 | if (IsEmpty()) |
075 | { |
076 | Console.WriteLine( "This Linear List Is Empty!" ); |
077 | return default (T); |
078 | } |
079 | if (i < 1 && i > this .Count()) |
080 | { |
081 | Console.WriteLine( "This Location Is Error!" ); |
082 | return default (T); |
083 | } |
084 | //指向头结点 |
085 | DoubleLinkedListNode<t> listNode = this .nHead; |
086 | int j = 1; |
087 | while (j <= i) |
088 | { |
089 | //移动节点,指向下一结点 |
090 | listNode = listNode.Next; |
091 | j++; |
092 | } |
093 | //获取数据 |
094 | return listNode.Data; |
095 | } |
096 |
097 | /// <summary> |
098 | /// 获取指定元素的位置 |
099 | /// </summary> |
100 | /// <param name="item">指定元素 |
101 | /// <returns>返回链表位置</returns> |
102 | public int LocateElement(T item) |
103 | { |
104 | if (IsEmpty()) |
105 | { |
106 | Console.WriteLine( "Linear List Is Empty!" ); |
107 | return 0; |
108 | } |
109 | int result = 0; |
110 | //指向头结点 |
111 | DoubleLinkedListNode<t> listNode = this .nHead; |
112 | //遍历双向链表,指针指向表尾,循环结束 |
113 | while (listNode.Next != null ) |
114 | { |
115 | result++; |
116 | //比较链表元素与指定元素是否相等 |
117 | if (listNode.Next.Data.Equals(item)) |
118 | { |
119 | return result; |
120 | } |
121 | //移动指针,指向下一结点 |
122 | listNode = listNode.Next; |
123 | } |
124 | return 0; |
125 | } |
126 |
127 | } |
插入操作
◆ 链表创建
◆ 指定元素后面插入新元素
◆ 指定元素前面插入新元素
001 | /// <summary> |
002 | /// 以“头插法”创建双向链表 |
003 | /// </summary> |
004 | /// <param name="item">待插入元素 |
005 | public void CreateListHead(T item) |
006 | { |
007 | //待插入结点 |
008 | DoubleLinkedListNode<t> firstNode = new DoubleLinkedListNode<t>(item); |
009 | //链表为空 |
010 | if ( this .nHead.Next == null ) |
011 | { |
012 | //新结点作为第一结点 |
013 | this .nHead.Next = firstNode; |
014 | //新结点的前继结点指向头结点 |
015 | firstNode.Prev = this .Head; |
016 | } |
017 | else |
018 | { |
019 | //指向头结点 |
020 | DoubleLinkedListNode<t> listNode = this .nHead; |
021 | //新结点的前继结点指向头结点 |
022 | firstNode.Prev = listNode; |
023 | //原第一结点作为新结点的后继结点 |
024 | firstNode.Next = listNode.Next; |
025 | //新结点作为原第一结点的前继结点 |
026 | listNode.Next.Prev = firstNode; |
027 | //新结点作为头结点的后继结点 |
028 | listNode.Next = firstNode; |
029 | } |
030 | } |
031 |
032 | /// <summary> |
033 | /// 以“尾插法”创建双向链表 |
034 | /// </summary> |
035 | /// <param name="item">侍插入元素 |
036 | public void CreateListTail(T item) |
037 | { |
038 | //待插入结点 |
039 | DoubleLinkedListNode<t> lastNode = new DoubleLinkedListNode<t>(item); |
040 | if ( this .nHead.Next == null ) |
041 | { |
042 | //新结点作为第一结点 |
043 | this .nHead.Next = lastNode; |
044 | //新结点的前继结点指向头结点 |
045 | lastNode.Prev = this .nHead; |
046 | return ; |
047 | } |
048 | //指向头结点 |
049 | DoubleLinkedListNode<t> listNode = this .nHead; |
050 | //遍历到表尾结点 |
051 | while (listNode.Next != null ) |
052 | { |
053 | //移动指针,指向下一结点 |
054 | listNode = listNode.Next; |
055 | } |
056 | //最后的结点作为新结点的前继结点 |
057 | lastNode.Prev = listNode; |
058 | //新结点作为最后的结点 |
059 | listNode.Next = lastNode; |
060 | } |
061 |
062 | /// <summary> |
063 | /// 指定元素后面插入新元素 |
064 | /// </summary> |
065 | /// <param name="item">指定元素 |
066 | /// <param name="newItem">新元素 |
067 | public void InsertAfterByValue(T item, T newItem) |
068 | { |
069 | int location = LocateElement(item); |
070 | if (location < 1) |
071 | { |
072 | Console.WriteLine( "Inserted Error!" ); |
073 | return ; |
074 | } |
075 | //待插入结点 |
076 | DoubleLinkedListNode<t> insertNode = new DoubleLinkedListNode<t>(newItem); |
077 | //插入位置为第一结点位置 |
078 | if (location == 1) |
079 | { |
080 | //新结点的前继结点指向头结点 |
081 | insertNode.Prev = this .nHead; |
082 | //新结点作为第一结点 |
083 | this .nHead.Next = insertNode; |
084 | } |
085 | else |
086 | { |
087 | int j = 1; |
088 | //指向头结点 |
089 | DoubleLinkedListNode<t> listNode = this .nHead; |
090 | //遍历链表,移动指针,直到指针指向指定的结点 |
091 | while (j <= location) |
092 | { |
093 | //移动指针,批向下一结点 |
094 | listNode = listNode.Next; |
095 | j++; |
096 | } |
097 | //新结点的前继结点指向指定结点 |
098 | insertNode.Prev = listNode; |
099 | //指定结点的后继结点作为新结点的后继结点 |
100 | insertNode.Next = listNode.Next; |
101 | //指定结点的后继结点的前继结点指向新结点 |
102 | listNode.Next.Prev = insertNode; |
103 | //新结点作为指定结点的后继结点 |
104 | listNode.Next = insertNode; |
105 | } |
106 | } |
107 |
108 | /// <summary> |
109 | /// 指定元素之前插入新元素 |
110 | /// </summary> |
111 | /// <param name="item">指定元素 |
112 | /// <param name="newItem">新元素 |
113 | public void InsertBeforeByValue(T item, T newItem) |
114 | { |
115 | InsertByLocation(newItem, LocateElement(item)); |
116 | } |
117 |
118 | /// <summary> |
119 | /// 在指定位置插入元素 |
120 | /// </summary> |
121 | /// <param name="item">新元素 |
122 | /// <param name="location">链表位置 |
123 | public void InsertByLocation(T item, int location) |
124 | { |
125 | if (location < 1 && location > this .Count()) |
126 | { |
127 | Console.WriteLine( "Location Is Error!" ); |
128 | return ; |
129 | } |
130 | //待插入结点 |
131 | DoubleLinkedListNode<t> insertNode = new DoubleLinkedListNode<t>(item); |
132 | //插入位置为第一结点位置 |
133 | if (location == 1) |
134 | { |
135 | //新结点作为第一结点 |
136 | this .nHead.Next = insertNode; |
137 | //新结点的前继结点指向头结点 |
138 | insertNode.Prev = this .nHead; |
139 | } |
140 | else |
141 | { |
142 | //指向头结点 |
143 | DoubleLinkedListNode<t> listNode = this .nHead; |
144 | int j = 1; |
145 | //遍历链表,移动指针,直到指向该位置的前一结点,遍历结束 |
146 | while (j < location) |
147 | { |
148 | listNode = listNode.Next; |
149 | j++; |
150 | } |
151 | //新结点的前继结点指向指定结点 |
152 | insertNode.Prev = listNode; |
153 | //指定结点的后继结点作为新结点的后继结点 |
154 | insertNode.Next = listNode.Next; |
155 | //指定结点的后继结点的前继结点指向新结点 |
156 | listNode.Next.Prev = insertNode; |
157 | //新结点作为指定结点的后继结点 |
158 | listNode.Next = insertNode; |
159 | } |
160 | } |
删除操作
01 | /// <summary> |
02 | /// 删除指定位置的元素 |
03 | /// </summary> |
04 | /// <param name="i">链表位置 |
05 | public void Delete( int i) |
06 | { |
07 | if (IsEmpty()) |
08 | { |
09 | Console.WriteLine( "This Linear List Is Empty!" ); |
10 | return ; |
11 | } |
12 | if (i < 1 && i > this .Count()) |
13 | { |
14 | Console.WriteLine( "Location Is Error!" ); |
15 | return ; |
16 | } |
17 | int j = 1; |
18 | //指向头结点 |
19 | DoubleLinkedListNode<t> listNode = this .nHead; |
20 | //遍历链表,移动指针,直到指针指向要删除结点的位置 |
21 | while (j <= i) |
22 | { |
23 | listNode = listNode.Next; |
24 | j++; |
25 | } |
26 | //链表只有一个结点以及要删除的结点为最后一个结点的情况 |
27 | if ( this .Count() == 1 || i == this .Count()) |
28 | { |
29 | //删除结点的前继结点的后继结点设为NULL |
30 | listNode.Prev.Next = null ; |
31 | } |
32 | else |
33 | { |
34 | //删除结点的后继结点作为删除结点的前继结点的后继结点 |
35 | listNode.Prev.Next = listNode.Next; |
36 | //删除结点的前继结点作为删除结点的后继结点的前继结点 |
37 | listNode.Next.Prev = listNode.Prev; |
38 | } |
39 |
40 | } |