顺序表

线性表是最常用且最简单的一种数据结构。简言之,一个线性表是n个数据元素的有限序列。线性表的顺序表示指的是一组地址连续的存储单元依次存储线性表的数据元素。线性表的顺序存储结构是一种随机存取的存储结构。

由于c#中的数组类型也有随机存取的特性,因此,通常采用数组来描述数据结构中的顺序存储结构。

为了能够复用代码,采用泛型类的设计。

这里要说明以下,由于.NET提供的关于线性表的类(如:ArrayLIst,SortedList)采用下标从0开始的索引值设计。所以,为了学习使用方便。以下代码中,关于“第i个”元素,都是从0开始算起的。

1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Text;
5
6 namespace 线性表
7 {
8 public class SeqList<T> where T:IComparable<T>
9 {
10
11 private int length; //线性表表的当前长度
12 private const int INITIAL_SIZE = 10; //线性表存储空间的初始分配量
13 private const int LIST_INCREMENT = 5; //线性表存储空间的分配增量
14 private int listSize; //当前分配的存储容量
15 private T[] lists; //数组,用于存储数据
16
17 #region 构造函数
18
19 public SeqList()
20 {
21 lists = new T[INITIAL_SIZE];
22 this.length = 0;
23 this.listSize = INITIAL_SIZE;
24 }
25
26 public SeqList(int size)
27 {
28 if (size < 0)
29 {
30 throw new ArgumentException("ArgumentException:线性表长度不能小于0.");
31 }
32 lists = new T[size];
33 this.length = 0;
34 this.listSize = size;
35 }
36 #endregion
37
38 #region 属性和索引器
39
40 //线性表长度Length属性
41 public int Length
42 {
43 get { return length; }
44 }
45
46 //线性表容量Capacity属性
47 public int Capacity
48 {
49 get { return listSize; }
50 }
51
52 //索引器,可以使像使用数组一样引用线性表中的元素
53 public T this[int index]
54 {
55 get { return lists[index]; }
56 set { lists[index] = value; }
57 }
58 #endregion
59
60 /// <summary>
61 /// 如果线性表容量不够用,增加容量。
62 /// </summary>
63 private void enlargeIfFull()
64 {
65 if (this.length == this.listSize)
66 {
67 int bigger = length + LIST_INCREMENT;
68 this.listSize = bigger;
69
70 T[] moreLists = new T[bigger];
71 this.lists.CopyTo(moreLists, 0); //复制元素到新的数组
72
73 this.lists = moreLists; //指向新的数组
74 }
75 }
76
77 #region 顺序表常规操作
78 /// <summary>
79 /// 获取线性表长度
80 /// </summary>
81 /// <returns>长度</returns>
82 public int GetLength()
83 {
84 return this.length;
85 }
86
87 /// <summary>
88 /// 清空线性表
89 /// </summary>
90 public void Clear()
91 {
92 this.length = 0;
93 }
94
95 /// <summary>
96 /// 判断是否为空
97 /// </summary>
98 /// <returns></returns>
99 public bool IsEmpty()
100 {
101 return length == 0;
102 }
103
104 /// <summary>
105 /// 添加操作,在末尾添加元素
106 /// </summary>
107 /// <param name="item">需要添加的元素</param>
108 public void Add(T item)
109 {
110 enlargeIfFull();
111
112 lists[length++] = item;
113 }
114
115 /// <summary>
116 /// 插入操作,i为从0开始的索引值
117 /// </summary>
118 /// <param name="i">索引值,从0开始</param>
119 /// <param name="item">插入的元素</param>
120 public void Insert(int i, T item)
121 {
122 if (i < 0 || i > this.length)
123 {
124 throw new ArgumentException("ArgumentException:参数不合法,无法执行插入操作");
125 }
126
127 enlargeIfFull();
128
129 for (int j = this.length - 1; j >= i; j--)
130 {
131 lists[j + 1] = lists[j]; //插入位置及之后的元素后移
132 }
133
134 lists[i] = item; //插入item
135 this.length++; //表长增1
136
137 }
138
139 /// <summary>
140 /// 删除操作
141 /// </summary>
142 /// <param name="i">索引值,从0开始</param>
143 /// <returns></returns>
144 public T Delete(int i)
145 {
146 if (i < 0 || i > this.length-1)
147 {
148 throw new ArgumentException("ArgumentException:参数不合法,无法执行删除操作");
149 }
150
151 T del = lists[i]; //被删除元素赋值给del
152
153 for (int j = i; j < this.length - 1; j++)
154 {
155 lists[j] = lists[j + 1]; //被删除元素之后的元素前移
156 }
157
158 this.length--; //表长减1
159 return del; //返回被删除元素
160 }
161
162 /// <summary>
163 /// 获取元素,该方法与索引器效果相同
164 /// </summary>
165 /// <param name="i">索引值,从0开始</param>
166 /// <returns>元素值</returns>
167 public T GetElem(int i)
168 {
169 if (i < 0|| i > this.length-1)
170 {
171 throw new ArgumentException("ArgumentException:参数不合法,无法获取元素");
172 }
173
174 return lists[i];
175 }
176
177 /// <summary>
178 /// 定位元素位置,相当于IndexOf方法
179 /// </summary>
180 /// <param name="item">元素</param>
181 /// <returns>索引值,从0开始</returns>
182 public int Locate(T item)
183 {
184 int i = 0; //i的初始值为第0个元素的位置
185
186 while (i < this.length && !item.Equals(lists[i]))
187 {
188 i++;
189 }
190
191 if (i <=this.length-1)
192 return i;
193 else
194 return -1;
195
196 }
197
198 /// <summary>
199 /// 倒置操作
200 /// </summary>
201 public void Reverse()
202 {
203 if (this.length == 0)
204 {
205 throw new InvalidOperationException("InvalidOperationException:线性表为空,无法执行倒置操作");
206 }
207
208 int i = 0;
209 int j = this.length / 2;
210 while (i < j)
211 {
212 T tmp = lists[i];
213 lists[i] = lists[this.length-1- i];
214 lists[this.length-1- i] =tmp;
215 i++;
216 }
217 }
218
219 /// <summary>
220 /// 合并操作,前提条件是当前线性表和other线性表按非递减有序排列
221 /// </summary>
222 /// <typeparam name="TItem">泛型</typeparam>
223 /// <param name="other">另外一个线性表</param>
224 /// <returns>合并后的线性表</returns>
225 public SeqList<T> Merge<TItem>(SeqList<T> other) where TItem:T
226 {
227 SeqList<T> sList = new SeqList<T>();
228 int i = 0; //当前线性表的循环变量
229 int j = 0; //other线性表的循环变量
230 while (i <= this.length - 1 && j <= other.length - 1)
231 {
232 if (lists[i].CompareTo(other[j]) < 0 || lists[i].CompareTo(other[j]) == 0)
233 {
234 sList.Add(lists[i++]);
235 }
236 else
237 {
238 sList.Add(other[j++]);
239 }
240 }
241
242 while (i <= this.length - 1)
243 {
244 sList.Add(lists[i++]);
245 }
246 while (j <= other.length-1)
247 {
248 sList.Add(other[j++]);
249 }
250 return sList;
251 }
252
253 /// <summary>
254 ///并集操作,将当前线性表表中没有,other中有的元素插入表末尾
255 /// </summary>
256 /// <param name="other"></param>
257 public void Union(SeqList<T> other)
258 {
259 int len = this.length;
260 for (int i = 0; i < other.length; i++)
261 {
262 T tmp =other[i];
263 if (this.Locate(tmp) == -1)
264 {
265 this.Insert(len++, tmp);
266 }
267
268 }
269 }
270 #endregion
271
272 }
273 }

posted on 2011-03-31 20:29  DongLiYang  阅读(582)  评论(0编辑  收藏  举报

导航