数据结构(C#语言版)——线性表
2011-01-09 20:48
447 查看
线性表
线性表(List):由n(n>=0)个相同类型的数据元素构成的有限序列。简记L=(D,R) D:数据元素的有限集合;R:数据元素之间关系的有限集合。
线性表的基本操作:求长度、清空操作、判断线性表是否为空、附加操作、插入操作、删除操作、取表元。
/// <summary>
/// 线性表的基本操作接口
/// 线性表(List):由n(n>=0)个相同类型的数据元素构成的有限序列。
/// 简记L=(D,R) D:数据元素的有限集合;R:数据元素之间关系的有限集合。
/// </summary>
/// <typeparam name="T">元素类型</typeparam>
public interface IList<T>: IEnumerable<T> {
/// <summary>
/// 列表长度
/// </summary>
int Count { get;}
/// <summary>
/// 清空列表
/// </summary>
void Clear();
/// <summary>
/// 判断是否为空
/// </summary>
bool IsEmpty { get;}
/// <summary>
/// 添加一个数据项至列表尾部
/// </summary>
/// <param name="value">插入项</param>
void Add(T value);
/// <summary>
/// 在指定位置插入一个数据项
/// </summary>
/// <param name="value">数据项</param>
/// <param name="index">位置</param>
void Insert(T value, int index);
/// <summary>
/// 删除指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
void Delete(int index);
/// <summary>
/// 获取指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据项</returns>
T this[int index] { get; set;}
}
顺序表
在内存中用一块地址连续的空间依次存放线性表的数据元素,这种方式存储的线性表叫顺序表。顺序表是用地址连续的存储单元顺序存储线性表中的各个数据元素,逻辑上相邻的数据元素在物理位置上也相邻。因此,在顺序表中查找任何一个位置上的数据元素非常方便,这是顺序存储的优点。但是,在对顺序表进行插入和删除时,需要通过移动数据元素来实现 ,影响了运行效率。
顺序表实现:
public class SequenceList<T> : IList<T> {
private const int Step = 16;
private int _capacity;
private T[] _datas;
private int _last = -1;
public SequenceList() : this(Step) {}
public SequenceList(int capacity) {
this._capacity = capacity;
this._datas = new T[capacity];
}
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator() {
int index = 0;
while(index<=this._last) {
yield return this._datas[index++];
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region Implementation of IList<T>
/// <summary>
/// 列表长度
/// </summary>
public int Count {
get {return this._last + 1;}
}
/// <summary>
/// 清空列表
/// </summary>
public void Clear() {
this._last = -1;
}
/// <summary>
/// 判断是否为空
/// </summary>
public bool IsEmpty {
get {return this._last == -1;}
}
/// <summary>
/// 添加一个数据项至列表尾部
/// </summary>
/// <param name="value">插入项</param>
public void Add(T value) {
if(this._last+1==this._capacity) {
Reassign();
}
this._last++;
this._datas[this._last] = value;
}
private void Reassign() {
this._capacity += Step;
T[] newDatas = new T[this._capacity];
int index = 0;
while(index<=this._last) {
newDatas[index] = this._datas[index];
index++;
}
this._datas = newDatas;
}
/// <summary>
/// 在指定位置插入一个数据项
/// </summary>
/// <param name="value">数据项</param>
/// <param name="index">位置</param>
public void Insert(T value, int index) {
CheckIndex(index);
if(this._last+1==this._capacity) {
Reassign();
}
this._last++;
int tempIndex = this._last;
while(tempIndex>index) {
this._datas[tempIndex] = this._datas[tempIndex - 1];
tempIndex--;
}
this._datas[tempIndex] = value;
}
private void CheckIndex(int index) {
if(index<0 || index>this._last) {
throw new ArgumentException("不正确的位置。");
}
}
/// <summary>
/// 删除指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
public void Delete(int index) {
CheckIndex(index);
int tempIndex = index;
while(tempIndex<this._last) {
this._datas[tempIndex] = this._datas[tempIndex + 1];
tempIndex++;
}
this._last--;
}
/// <summary>
/// 获取指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据项</returns>
public T this[int index] {
get {
CheckIndex(index);
return this._datas[index];
}
set {
CheckIndex(index);
this._datas[index] = value;
}
}
#endregion
}
顺序表测试:
[TestClass]
public class SequenceListTest {
/// <summary>
/// 已知顺序表L,写一算法将其倒置
/// 11,23,36,45,80,60,40,6
/// </summary>
[TestMethod]
public void Revers() {
SequenceList<int> l = new SequenceList<int>();
l.Add(11);
l.Add(23);
l.Add(36);
l.Add(45);
l.Add(80);
l.Add(60);
l.Add(40);
l.Add(6);
for(int i = 0; i < l.Count / 2; i++) {
int temp = l[i];
l[i] = l[l.Count - 1 - i];
l[l.Count - 1 - i] = temp;
}
foreach(var i in l) {
Console.WriteLine(i);
}
}
/// <summary>
/// 有数据类型为整形的顺序表La和Lb,其数据元素均按从小到大的升序排列。
/// 编写一个算法将它们合并成一个表Lc,要求Lc中数据元素也按升序排列。
/// 1,2,5,7
/// 3,4,6,8,9
/// </summary>
[TestMethod]
public void Merge() {
SequenceList<int> la = new SequenceList<int>();
la.Add(1);
la.Add(2);
la.Add(5);
la.Add(7);
SequenceList<int> lb = new SequenceList<int>();
lb.Add(3);
lb.Add(4);
lb.Add(6);
lb.Add(8);
lb.Add(9);
int aIndex = 0;
int bIndex = 0;
SequenceList<int> lc = new SequenceList<int>();
while(aIndex < la.Count && bIndex < lb.Count) {
if(la[aIndex] <= lb[bIndex]) {
lc.Add(la[aIndex]);
aIndex++;
}
else {
lc.Add(lb[bIndex]);
bIndex++;
}
}
while(aIndex < la.Count) {
lc.Add(la[aIndex]);
aIndex++;
}
while(bIndex < lb.Count) {
lc.Add(lb[bIndex]);
bIndex++;
}
foreach(var i in lc) {
Console.WriteLine(i);
}
}
/// <summary>
/// 已知一个存储整数的顺序表La,试构造顺序表Lb,要求顺序表Lb中只包含顺序表La中所有值不相同的数据元素。
/// 11,23,23,36,45,36,80,11,60,40,6, 6
/// </summary>
[TestMethod]
public void Purge() {
SequenceList<int> la = new SequenceList<int>();
la.Add(11);
la.Add(23);
la.Add(23);
la.Add(36);
la.Add(45);
la.Add(36);
la.Add(80);
la.Add(11);
la.Add(60);
la.Add(40);
la.Add(6);
la.Add(6);
SequenceList<int> lb = new SequenceList<int>();
lb.Add(la[0]);
for(int i = 1; i < la.Count; i++) {
int j = 0;
for(; j < lb.Count; j++) {
if(la[i] == lb[j]) {
break;
}
}
if(j == lb.Count) {
lb.Add(la[i]);
}
}
foreach(var i in lb) {
Console.WriteLine(i);
}
}
}
链表
链式存储,这样的线性表叫链表(Lnked List)。链表不要求逻辑上相邻的数据元素在物理存储位置上也相邻,因此,在对链表进行插入和删除时不需要移动数据元素,但同时也失去了顺序表可随机存储的优点。单链表实现:
public class OneWayNode<T> {
private OneWayNode<T> _next;
private T _value;
public OneWayNode() : this(default(T), null) {
}
public OneWayNode(T value) : this(value, null) {
}
public OneWayNode(T value, OneWayNode<T> next) {
this._value = value;
this._next = next;
}
public OneWayNode<T> Next {
get {return this._next;}
set { this._next = value;}
}
public T Value {
get {return this._value;}
set { this._value = value;}
}
}
public class OneWayLinkList<T> : IList<T> {
private OneWayNode<T> _head;
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator() {
OneWayNode<T> node = this.Head;
while(node!=null) {
yield return node.Value;
node = node.Next;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region Implementation of IList<T>
/// <summary>
/// 列表长度
/// </summary>
public int Count {
get {
int count = 0;
OneWayNode<T> node = this._head;
while(node!=null) {
count++;
node = node.Next;
}
return count;
}
}
/// <summary>
/// 清空列表
/// </summary>
public void Clear() {
this._head = null;
}
/// <summary>
/// 判断是否为空
/// </summary>
public bool IsEmpty {
get {return this.Head == null;}
}
public OneWayNode<T> Head {
get {return this._head;}
set { this._head = value;}
}
/// <summary>
/// 添加一个数据项至列表尾部
/// </summary>
/// <param name="value">插入项</param>
public void Add(T value) {
if(this.Head == null) {
this.Head = new OneWayNode<T>(value);
return;
}
OneWayNode<T> node = this.Head;
while(node.Next!=null) {
node = node.Next;
}
node.Next = new OneWayNode<T>(value);
}
/// <summary>
/// 在指定位置插入一个数据项
/// </summary>
/// <param name="value">数据项</param>
/// <param name="index">位置</param>
public void Insert(T value, int index) {
CheckIndex(index);
if(index==0) {
this._head = new OneWayNode<T>(value, this._head);
return;
}
OneWayNode<T> prev = this._head;
OneWayNode<T> next = this._head.Next;
int tempIndex = 1;
while(tempIndex<index) {
prev = next;
next = next.Next;
tempIndex++;
}
prev.Next = new OneWayNode<T>(value, next);
}
private void CheckIndex(int index) {
if(index<0 || index>=Count) {
throw new ArgumentException("不正确的位置。");
}
}
/// <summary>
/// 删除指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
public void Delete(int index) {
if(index==0) {
this._head = this._head.Next;
return;
}
OneWayNode<T> prev = this._head;
OneWayNode<T> next = this._head.Next;
int tempIndex = 1;
while(tempIndex < index) {
prev = next;
next = next.Next;
tempIndex++;
}
prev.Next = next.Next;
}
/// <summary>
/// 获取指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据项</returns>
public T this[int index] {
get {
OneWayNode<T> current = GetItem(index);
return current.Value;
}
set {
OneWayNode<T> current = GetItem(index);
current.Value = value;
}
}
private OneWayNode<T> GetItem(int index) {
OneWayNode<T> current = this.Head;
int tempIndex = 0;
while(tempIndex < index) {
current = current.Next;
tempIndex++;
}
return current;
}
#endregion
}
单链表测试:
[TestClass]
public class OneWayLinkListTest {
/// <summary>
/// 已知顺序表L,写一算法将其倒置
/// 11,23,36,45,80,60,40,6
/// </summary>
[TestMethod]
public void Revers() {
OneWayLinkList<int> l = new OneWayLinkList<int>();
l.Add(11);
l.Add(23);
l.Add(36);
l.Add(45);
l.Add(80);
l.Add(60);
l.Add(40);
l.Add(6);
OneWayNode<int> node = l.Head;
l.Head = null;
while(node != null) {
OneWayNode<int> next = node.Next;
node.Next = l.Head;
l.Head = node;
node = next;
}
foreach(var i in l) {
Console.WriteLine(i);
}
}
/// <summary>
/// 有数据类型为整形的顺序表La和Lb,其数据元素均按从小到大的升序排列。
/// 编写一个算法将它们合并成一个表Lc,要求Lc中数据元素也按升序排列。
/// 1,2,5,7
/// 3,4,6,8,9
/// </summary>
[TestMethod]
public void Merge() {
OneWayLinkList<int> la = new OneWayLinkList<int>();
la.Add(1);
la.Add(2);
la.Add(5);
la.Add(7);
OneWayLinkList<int> lb = new OneWayLinkList<int>();
lb.Add(3);
lb.Add(4);
lb.Add(6);
lb.Add(8);
lb.Add(9);
OneWayNode<int> aNode = la.Head;
OneWayNode<int> bNode = lb.Head;
OneWayLinkList<int> lc = new OneWayLinkList<int>();
while(aNode != null && bNode != null) {
if(aNode.Value <= bNode.Value) {
lc.Add(aNode.Value);
aNode = aNode.Next;
}
else {
lc.Add(bNode.Value);
bNode = bNode.Next;
}
}
while(aNode != null) {
lc.Add(aNode.Value);
aNode = aNode.Next;
}
while(bNode != null) {
lc.Add(bNode.Value);
bNode = bNode.Next;
}
foreach(var i in lc) {
Console.WriteLine(i);
}
}
/// <summary>
/// 已知一个存储整数的顺序表La,试构造顺序表Lb,要求顺序表Lb中只包含顺序表La中所有值不相同的数据元素。
/// 11,23,23,36,45,36,80,11,60,40,6, 6
/// </summary>
[TestMethod]
public void Purge() {
OneWayLinkList<int> la = new OneWayLinkList<int>();
la.Add(11);
la.Add(23);
la.Add(23);
la.Add(36);
la.Add(45);
la.Add(36);
la.Add(80);
la.Add(11);
la.Add(60);
la.Add(40);
la.Add(6);
la.Add(6);
OneWayLinkList<int> lb = new OneWayLinkList<int>();
lb.Add(la.Head.Value);
OneWayNode<int> aNode = la.Head.Next;
while(aNode!=null) {
OneWayNode<int> bNode = lb.Head;
while(bNode!=null) {
if(aNode.Value==bNode.Value) {
break;
}
bNode = bNode.Next;
}
if(bNode==null) {
lb.Add(aNode.Value);
}
aNode = aNode.Next;
}
foreach(var i in lb) {
Console.WriteLine(i);
}
}
}
双链表实现:
public class TwoWayNode<T> {
private TwoWayNode<T> _next;
private TwoWayNode<T> _prev;
private T _value;
public TwoWayNode() : this(default(T), null, null) {
}
public TwoWayNode(T value)
: this(value, null, null) {
}
public TwoWayNode(T value, TwoWayNode<T> prev, TwoWayNode<T> next) {
this._value = value;
this._prev = prev;
this._next = next;
}
public TwoWayNode<T> Next {
get {return this._next;}
set { this._next = value;}
}
public TwoWayNode<T> Previous {
get {return this._prev;}
set { this._prev = value;}
}
public T Value {
get {return this._value;}
set { this._value = value;}
}
}
public class TwoWayLinkList<T> : IList<T> {
private TwoWayNode<T> _head;
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator() {
TwoWayNode<T> node = this.Head;
while(node != null) {
yield return node.Value;
node = node.Next;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region Implementation of IList<T>
/// <summary>
/// 列表长度
/// </summary>
public int Count {
get {
int count = 0;
TwoWayNode<T> node = this._head;
while(node != null) {
count++;
node = node.Next;
}
return count;
}
}
/// <summary>
/// 清空列表
/// </summary>
public void Clear() {
this._head = null;
}
/// <summary>
/// 判断是否为空
/// </summary>
public bool IsEmpty {
get {return this.Head == null;}
}
public TwoWayNode<T> Head {
get {return this._head;}
set { this._head = value;}
}
/// <summary>
/// 添加一个数据项至列表尾部
/// </summary>
/// <param name="value">插入项</param>
public void Add(T value) {
if(this.Head == null) {
this.Head = new TwoWayNode<T>(value);
return;
}
TwoWayNode<T> node = this.Head;
while(node.Next != null) {
node = node.Next;
}
node.Next = new TwoWayNode<T>(value, node, null);
}
/// <summary>
/// 在指定位置插入一个数据项
/// </summary>
/// <param name="value">数据项</param>
/// <param name="index">位置</param>
public void Insert(T value, int index) {
CheckIndex(index);
if(index == 0) {
this._head = new TwoWayNode<T>(value, null, this._head);
return;
}
TwoWayNode<T> current = this.GetItem(index);
current.Previous.Next = current.Next.Previous = new TwoWayNode<T>(value, current.Previous, current.Next);
}
private void CheckIndex(int index) {
if(index < 0 || index >= Count) {
throw new ArgumentException("不正确的位置。");
}
}
/// <summary>
/// 删除指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
public void Delete(int index) {
if(index == 0) {
this._head = this._head.Next;
return;
}
TwoWayNode<T> current = this.GetItem(index);
current.Previous.Next = current.Next;
current.Next.Previous = current.Previous;
}
/// <summary>
/// 获取指定位置的数据项
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据项</returns>
public T this[int index] {
get {
TwoWayNode<T> current = GetItem(index);
return current.Value;
}
set {
TwoWayNode<T> current = GetItem(index);
current.Value = value;
}
}
private TwoWayNode<T> GetItem(int index) {
TwoWayNode<T> current = this.Head;
int tempIndex = 0;
while(tempIndex < index) {
current = current.Next;
tempIndex++;
}
return current;
}
#endregion
}
双链表测试:
[TestClass]
public class TwoWayLinkListTest {
/// <summary>
/// 已知顺序表L,写一算法将其倒置
/// 11,23,36,45,80,60,40,6
/// </summary>
[TestMethod]
public void Revers() {
TwoWayLinkList<int> l = new TwoWayLinkList<int>();
l.Add(11);
l.Add(23);
l.Add(36);
l.Add(45);
l.Add(80);
l.Add(60);
l.Add(40);
l.Add(6);
TwoWayNode<int> node = l.Head;
l.Head = null;
while(node != null) {
TwoWayNode<int> next = node.Next;
node.Next = l.Head;
l.Head = node;
node = next;
}
foreach(var i in l) {
Console.WriteLine(i);
}
}
/// <summary>
/// 有数据类型为整形的顺序表La和Lb,其数据元素均按从小到大的升序排列。
/// 编写一个算法将它们合并成一个表Lc,要求Lc中数据元素也按升序排列。
/// 1,2,5,7
/// 3,4,6,8,9
/// </summary>
[TestMethod]
public void Merge() {
TwoWayLinkList<int> la = new TwoWayLinkList<int>();
la.Add(1);
la.Add(2);
la.Add(5);
la.Add(7);
TwoWayLinkList<int> lb = new TwoWayLinkList<int>();
lb.Add(3);
lb.Add(4);
lb.Add(6);
lb.Add(8);
lb.Add(9);
TwoWayNode<int> aNode = la.Head;
TwoWayNode<int> bNode = lb.Head;
TwoWayLinkList<int> lc = new TwoWayLinkList<int>();
while(aNode != null && bNode != null) {
if(aNode.Value <= bNode.Value) {
lc.Add(aNode.Value);
aNode = aNode.Next;
}
else {
lc.Add(bNode.Value);
bNode = bNode.Next;
}
}
while(aNode != null) {
lc.Add(aNode.Value);
aNode = aNode.Next;
}
while(bNode != null) {
lc.Add(bNode.Value);
bNode = bNode.Next;
}
foreach(var i in lc) {
Console.WriteLine(i);
}
}
/// <summary>
/// 已知一个存储整数的顺序表La,试构造顺序表Lb,要求顺序表Lb中只包含顺序表La中所有值不相同的数据元素。
/// 11,23,23,36,45,36,80,11,60,40,6, 6
/// </summary>
[TestMethod]
public void Purge() {
TwoWayLinkList<int> la = new TwoWayLinkList<int>();
la.Add(11);
la.Add(23);
la.Add(23);
la.Add(36);
la.Add(45);
la.Add(36);
la.Add(80);
la.Add(11);
la.Add(60);
la.Add(40);
la.Add(6);
la.Add(6);
TwoWayLinkList<int> lb = new TwoWayLinkList<int>();
lb.Add(la.Head.Value);
TwoWayNode<int> aNode = la.Head.Next;
while(aNode!=null) {
TwoWayNode<int> bNode = lb.Head;
while(bNode!=null) {
if(aNode.Value==bNode.Value) {
break;
}
bNode = bNode.Next;
}
if(bNode==null) {
lb.Add(aNode.Value);
}
aNode = aNode.Next;
}
foreach(var i in lb) {
Console.WriteLine(i);
}
}
}
相关文章推荐
- 数据结构(线性表):双循环链表
- 数据结构之线性表
- Java数据结构之线性表(2)
- 数据结构1:线性表的顺序表示和实现
- 【Data】数据结构之线性表(2)
- 数据结构5:线性表中把属于la中而不属于lb中的元素放到la中
- 数据结构(线性表)
- 数据结构(11)线性表之一元多项式表示及相加
- 数据结构之线性表 -- 链表(总括)
- 数据结构之线性队列
- 数据结构基础温故-1.线性表(上)
- JAVA数据结构之线性表的链式存储结构——循环链表
- 【数据结构】顺序线性表的构造和存储数据
- 数据结构——线性结构(9)——Vector的实现过程详解
- 【数据结构】顺序线性表的几种常用方法
- 离散数据结构,线性数据结构
- 数据结构之线性表-链式存储之循环链表(三)
- 数据结构之线性表、栈、队列
- 数据结构(严蔚敏)C语言实现---线性表的顺序存储
- 数据结构之线性表(顺序表)的基本操作