飘遥的Blog

C/C++/.NET
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

数据结构(C#):顺序表

Posted on 2008-12-06 15:40  Zzx飘遥  阅读(664)  评论(1编辑  收藏  举报
线性表是有限个数据元素的序列。线性表的存储有顺序存储和链式存储两种。

为使线性表支持相同的API,定义了以下接口,分别用顺表和链表实现。
/*
* File     :   ILinerList.cs
* Author   :   Zhenxing Zhou
* Date     :   2008-12-06
* Blog     :  
http://www.xianfen.net/
*/
using System.Collections.Generic;
namespace Xianfen.Net.DataStructure
{
    
interface ILinearList<T> : IEnumerable<T>
    {
        
void Add(T t);
        
void AddHead(T t);
        
void AddTail(T t);
        
void Clear();
        
int Count { get; }
        
int Find(T t);
        T GetAt(
int pos);
        T GetHead();
        T GetTail();
        
void InsertAt(T t, int pos);
        
bool IsEmpty { get; }
        
void RemoveAll();
        
void RemoveAt(int pos);
        
void RemoveHead();
        
void RemoveTail();
        
void SetAt(int pos, T t);
    }
}

本篇实现顺序表的存取。顺序表的存取有很多中实现方式。
线性表的顺序存储是指用一组地址连续的存储单元以此存储线性表的元素。两个逻辑相邻的元素在物理上也是相邻的,能够快速取得指定索引的元素;但插入、删除元素时需要移动元素,效率较低;存储区是连续的,长度一般不能在原存储区的基础上扩大,扩大存储区需要复制原来的元素。
代码实现:
/*
* File     :   SequentialList.cs
* Author   :   Zhenxing Zhou
* Date     :   2008-12-06
* Blog     :  
http://www.xianfen.net/
*/
using System;
using System.Collections;
using System.Collections.Generic;

namespace Xianfen.Net.DataStructure
{
    
public class SequentialList<T> : ILinearList<T>
    {
        
private T[] m_List;
        
private int m_Count;
        
private int m_Capacity;

        
public int Count
        {
            
get { return m_Count; }
        }

        
public bool IsEmpty
        {
            
get { return m_Count == 0; }
        }

        
public SequentialList()
            :
this(16)
        {
        }

        
public SequentialList(int capacity)
        {
            m_Count
= 0;
            m_Capacity
= capacity;
            m_List
= new T[m_Capacity];
        }

        
public void Add(T t)
        {
            InsertAt(t, m_Count);
        }

        
public void AddHead(T t)
        {
            InsertAt(t,
0);
        }

        
public void AddTail(T t)
        {
            Add(t);
        }

        
public void Clear()
        {
            m_Count
= 0;
        }

        
public int Find(T t)
        {
            
for (int i = 0; i < m_Count; i++)
            {
                
if (m_List[i].Equals(t))
                {
                    
return i;
                }
            }

            
return -1;
        }

        
public T GetAt(int pos)
        {
            
if (pos >= m_Count || pos < 0)
            {
                
throw new IndexOutOfRangeException("pos");
            }

            
return m_List[pos];
        }

        
public T GetHead()
        {
            
return m_List[0];
        }

        
public T GetTail()
        {
            
return m_List[m_Count - 1];
        }

        
public void InsertAt(T t, int pos)
        {
            
if (pos > m_Count)
            {
                
throw new IndexOutOfRangeException("pos");
            }

            
if (m_Count == int.MaxValue)
            {
                
throw new ArithmeticException();
            }

            EnsureCapacity();

            
for (int i = m_Count - 1; i >= pos; i--)
            {
                m_List[i
+ 1] = m_List[i];
            }

            m_List[pos]
= t;
            m_Count
++;
        }

        
public void RemoveAll()
        {
            Clear();
        }

        
public void RemoveAt(int pos)
        {
            
if (pos >= m_Count || pos < 0)
            {
                
throw new IndexOutOfRangeException("pos");
            }

            
for (int i = pos; i < m_Count; i++)
            {
                m_List[i]
= m_List[i + 1];
            }

            m_Count
--;
        }

        
public void RemoveHead()
        {
            RemoveAt(
0);
        }

        
public void RemoveTail()
        {
            RemoveAt(m_Count
- 1);
        }

        
public void SetAt(int pos, T t)
        {
            
if (pos >= m_Count || pos < 0)
            {
                
throw new IndexOutOfRangeException("pos");
            }

            m_List[pos]
= t;
        }

        
// 空间不足时,重新分配足够大的空间,原内容复制到新的空间。
        
// 分配算法类似与StringBuilder的空间再分配方式。
        private void EnsureCapacity()
        {
            
if (m_Count + 1 > m_Capacity)
            {
                m_Capacity
*= 2;

                
if (m_Count + 1 > m_Capacity)
                {
                    m_Capacity
= m_Count + 1;
                }

                T[] tempArray
= new T[m_Capacity];

                
for (int i = 0; i < m_Count; i++)
                {
                    tempArray[i]
= m_List[i];
                }

                m_List
= tempArray;
            }
        }

        
public IEnumerator<T> GetEnumerator()
        {
            
for (int i = 0; i < m_Count; i++)
            {
                
yield return m_List[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            
return GetEnumerator();
        }
    }
}

如果发现BUG请留言指出,下一篇介绍单链表的实现。