您的位置:首页 > 理论基础 > 数据结构算法

数据结构(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);


}


}


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: