线性表
线性表:相同特性数据元素的有限序列
<1>有且只有一个头结点
<2>有且只有一个尾结点
<3>表头外所有元素都有一个直接前驱
<4>表尾外所有元素都有一个直接后继
线性表之顺序表
顺序表:逻辑上相邻,物理上也相邻
特性:地址连续,随机存取,类型相同,依次存放
线性表接口
namespace DataStruct.List
{
/// <summary>
/// 列表接口
/// </summary>
/// <typeparam name="T">列表数据类型</typeparam>
interface IList<T>
{
/// <summary>
/// 元素个数
/// </summary>
/// <returns>返回表中元素个数</returns>
public int Count { get; }
/// <summary>
/// 判断表是否为空
/// </summary>
/// <returns>返回是否为空</returns>
public bool IsEmpty();
/// <summary>
/// 增加元素
/// </summary>
/// <param name="val">元素变量</param>
public void Add(T val);
/// <summary>
/// 插入元素
/// </summary>
/// <param name="index">元素索引</param>
/// <param name="val">插入元素值</param>
public void Insert(int index, T val);
/// <summary>
/// 删除元素
/// </summary>
/// <param name="val">元素变量</param>
/// <returns>返回要删除的元素</returns>
public T Remove(T val);
/// <summary>
/// 索引器
/// </summary>
/// <param name="index">索引值</param>
/// <returns>返回对应数据</returns>
public T this[int index]
{
get; set;
}
/// <summary>
/// 查看数据在列表中的位置
/// </summary>
/// <param name="val">数据</param>
/// <returns>返回索引</returns>
public int? IndexOf(T val);
/// <summary>
/// 清理列表元素
/// </summary>
public void Clear();
/// <summary>
/// 判断列表是否包含某个元素
/// </summary>
/// <param name="val">元素</param>
/// <returns>返回是否包含</returns>
public bool IsContains(T val);
}
}
顺序表实现
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace DataStruct.List
{
class SequenceList<T> : IList<T>, IEnumerable<T>
where T:IComparable<T>
{
#region 数据域
/// <summary>
/// 列表元素个数
/// </summary>
private int count;
/// <summary>
/// 数据
/// </summary>
private T[] data;
/// <summary>
/// 默认列表大小
/// </summary>
private const int DEFAULT_SIZE = 10;
#endregion
#region 构造器
/// <summary>
/// 构造器
/// </summary>
public SequenceList()
{
this.data = new T[DEFAULT_SIZE];
}
/// <summary>
/// 构造器
/// </summary>
/// <param name="data">数组</param>
public SequenceList(params T[]data)
{
this.count = data.Length;
this.data = data;
}
#endregion
#region 辅助函数
/// <summary>
/// 检查索引
/// </summary>
/// <param name="index">索引</param>
private void RaiseForIndex(ref int index)
{
if (index < 0)
index += this.count;
if (index < 0 || index >= count)
throw new IndexOutOfRangeException("列表索引访问越界了");
}
/// <summary>
/// 检查增加索引
/// </summary>
/// <param name="index">索引</param>
private void RaiseForIndex_Add(int index)
{
if (index < 0)
index += this.count;
if (index < 0 || index > count)
throw new IndexOutOfRangeException("列表索引访问越界了");
}
/// <summary>
/// 检查区间
/// </summary>
/// <param name="index">索引</param>
private void RaiseForRange(ref int start,ref int end)
{
if (start < 0) start += count;
if (end < 0) end += count;
var cnt = end - start;
if (start < 0 || end < 0 || cnt <= 0||start>=count||end>count)
throw new IndexOutOfRangeException("列表索引访问越界了");
}
/// <summary>
/// 扩容
/// </summary>
private void Expand()
{
if (count >= data.Length)
Array.Resize<T>(ref data,data.Length+data.Length << 1);
}
#endregion
#region 实现接口
/// <summary>
/// 索引器
/// </summary>
/// <param name="index">索引值</param>
/// <returns>返回对应数据</returns>
public T this[int index]
{
get
{
RaiseForIndex(ref index);
return this.data[index];
}
set
{
RaiseForIndex(ref index);
this.data[index] = value;
}
}
/// <summary>
/// 增加元素
/// </summary>
/// <param name="val">元素变量</param>
public void Add(T val)
{
Expand();
this.data[count++] = val;
}
/// <summary>
/// 清理列表元素
/// </summary>
public void Clear() => this.count = 0;
/// <summary>
/// 获取给定元素的索引
/// </summary>
/// <param name="val">给定元素</param>
/// <returns>索引</returns>
public int? IndexOf(T val)
{
for (int i = 0; i < count; ++i)
{
if (val.CompareTo(data[i]) == 0)
return i;
}
return null;
}
/// <summary>
/// 插入元素
/// </summary>
/// <param name="index">元素索引</param>
/// <param name="val">插入元素值</param>
public void Insert(int index, T val)
{
RaiseForIndex_Add(index);
Expand();
for (int i = count; i >index; i--)
this.data[i] = this.data[i - 1];
this.data[index] = val;
this.count++;
}
/// <summary>
/// 获取元素个数
/// </summary>
public int Count => this.count;
/// <summary>
/// 判断是否为空
/// </summary>
/// <returns>是否为空</returns>
public bool IsEmpty()=>this.count == 0;
/// <summary>
/// 删除元素
/// </summary>
/// <param name="val">元素变量</param>
/// <returns>返回要删除的元素</returns>
public T Remove(int index)
{
RaiseForIndex(ref index);//检查越界
var temp = this.data[index];
for (int i = index; i < count; i++)
this.data[i] = this.data[i + 1];
this.count--;
return temp;
}
/// <summary>
/// 判断列表是否包含某个元素
/// </summary>
/// <param name="val">元素</param>
/// <returns>返回是否包含</returns>
public bool IsContains(T val)
{
return this.IndexOf(val).HasValue;
}
#endregion
#region 转化其他
/// <summary>
/// 覆盖ToString方法
/// </summary>
/// <returns>返回字符串</returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
bool tag = true;
for(int i=0;i<count;++i)
{
if (tag)
{
sb.Append(this.data[i] + "");
tag = false;
}
else
sb.Append(","+ this.data[i]);
}
sb.Append("]");
return sb.ToString();
}
/// <summary>
/// 转化为数组
/// </summary>
/// <returns></returns>
public T[]ToArray()=>this.data;
#endregion
/// <summary>
/// 显式类型转换
/// </summary>
/// <param name="array">数组</param>
public static implicit operator SequenceList<T>(T[]array)=>new SequenceList<T>(array);
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns>返回迭代器</returns>
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < this.count; i++)
yield return this.data[i];
}
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns>返回迭代器</returns>
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < this.count; i++)
yield return this.data[i];
}
/// <summary>
/// 范围添加
/// </summary>
/// <param name="collection">可迭代集合</param>
public void AddRange(IEnumerable<T> collection)
{
foreach (var item in collection)
{
this.Add(item);
}
}
/// <summary>
/// 范围移除
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
/// <returns>删除几个</returns>
public int RemoveRange(int start, int end)
{
RaiseForRange(ref start, ref end);
while (end<count)
this.data[start++] = this.data[end++];
this.count = start;
return start - end;
}
/// <summary>
/// 顺序表切片
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
/// <returns>切片结果</returns>
public SequenceList<T> this[(int start,int end) t]
{
get
{
TryCopy(this, out SequenceList<T> ans, t.start, t.end);
return ans;
}
}
/// <summary>
/// 顺序表切片
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
/// <returns>切片结果</returns>
public SequenceList<T> this[(int start, int end,int step) t]
{
get
{
if (t.step <= 0)
throw new IndexOutOfRangeException("列表索引访问越界了");
RaiseForRange(ref t.start, ref t.end);
var ls = new SequenceList<T>();
for (int i = t.start; i < t.end; i += t.step)
ls.Add(this[i]);
return ls;
}
}
/// <summary>
/// 顺序表1复制到顺序表2
/// </summary>
/// <param name="t1">顺序表1</param>
/// <param name="t2">顺序表2</param>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
public static bool TryCopy(SequenceList<T> t1, out SequenceList<T> t2, int start, int end)
{
if(start<0)start += t1.count;
if (end < 0) end += t1.count;
var cnt = end - start;
if (start < 0 || end < 0 || cnt <= 0 || start >= t1.count || end > t1.count)
{
t2 = null;
return false;
}
var t = new T[cnt];
Array.Copy(t1.data, start, t, 0, cnt);
t2 = new SequenceList<T>(t);
return true;
}
/// <summary>
/// 删除列表顶部元素
/// </summary>
/// <returns>返回被删除的元素值</returns>
public T Pop()
{
if (this.count == 0)
throw new IndexOutOfRangeException("列表为空!");
return this.data[--this.count];
}
/// <summary>
/// 列表逆置
/// </summary>
public void Reverse()
{
for (int i = 0; i < this.count/2; i++)
(data[i],data[count - i - 1]) = (data[count-i-1], this.data[i]);
}
/// <summary>
/// 划分问题
/// </summary>
/// <param name="val">值</param>
/// <param name="reverse">是否逆序</param>
public void Partition(T val,bool reverse=false)
{
int i = 0;
int j = count-1;
if(reverse)
{
while (i < j)
{
while (i < j && data[i].CompareTo(val) >= 0)
i++;
while (i < j && data[j].CompareTo(val) < 0)
j--;
if (i < j)
(data[i], data[j]) = (data[j], data[i]);
}
}
else
{
while (i < j)
{
while (i < j && data[i].CompareTo(val) <= 0)
i++;
while (i < j && data[j].CompareTo(val) > 0)
j--;
if (i < j)
(data[i], data[j]) = (data[j], data[i]);
}
}
}
/// <summary>
/// 元素左移
/// </summary>
public void MoveLeft()
{
var temp = this.data[0];
for (int i = 0; i < count-1; i++)
this.data[i] = this.data[i + 1];
this.data[count - 1] = temp;
}
/// <summary>
/// 元素右移
/// </summary>
public void MoveRight()
{
var temp = this.data[count - 1];
for (int i = count - 1; i > 0; i--)
data[i] = data[i - 1];
this.data[0] = temp;
}
/// <summary>
/// 运算符重载:添加元素
/// </summary>
/// <param name="x">顺序表</param>
/// <param name="val">值</param>
/// <returns>返回添加后的新表</returns>
public static SequenceList<T> operator +(SequenceList<T> x,T val)
{
TryCopy(x, out SequenceList<T> t, 0, x.count);
t.Add(val);
return t;
}
/// <summary>
/// 运算符重载:追加列表
/// </summary>
/// <param name="x">顺序表1</param>
/// <param name="y">顺序表2</param>
/// <returns>返回添加后的列表</returns>
public static SequenceList<T> operator+(SequenceList<T> x,SequenceList<T> y)
{
T[] data = new T[x.count + y.count];
Array.Copy(x.data, 0, data, 0, x.count);
Array.Copy(y.data, 0, data, x.count, y.count);
return new SequenceList<T>(data);
}
}
}
顺序表操作
创建
var a = new SequenceList<int>();
var b = new SequenceList<double>(1.0,2.3,3,4,5,6,7);
SequenceList<int> c= new int[] { 2, 3, 5, 7, 8 };
索引
WriteLine(b);//[1,2.3,3,4,5,6,7]
WriteLine(b[-1]);//7
切片
WriteLine(b[(0, 2)]);//[1,2.3]
WriteLine(c[(0, 5, 2)]);//[2,5,8]
WriteLine(c[(0, -1, 2)]);//[2,5]
基本操作
c.Add(5);
c.AddRange(new int[] { 6, 5, 8, 9 });
WriteLine(c.IsContains(5));//True
c.Insert(0, 10086);
WriteLine(c.IndexOf(5));//3
WriteLine(c);//[10086,2,3,5,7,8,5,6,5,8,9]
c.RemoveRange(0, 5);
WriteLine(c);//[8,5,6,5,8,8,5,6,5,8]
c.Clear();
列表复制
SequenceList<int> c= new int[] { 2, 3, 5, 7, 8 };
//深复制,返回新列表
c += 1;
c += 2;
c += 5;
WriteLine(c);//[2,3,5,7,8,1,2,5]
c.Pop();
c.Pop();
c.Pop();
c += new SequenceList<int>(5,7,8);
WriteLine(c);//[2,3,5,7,8,5,7,8]
其他
var a = new SequenceList<int>(1,5,7,8,9,6,5,3,0);
a.Reverse();
WriteLine(a);//[0,3,5,6,9,8,7,5,1]
a.MoveLeft();
WriteLine(a);//[3,5,6,9,8,7,5,1,0]
a.MoveRight();
WriteLine(a);//[0,3,5,6,9,8,7,5,1]
a.Partition(5, false);
WriteLine(a);//[0,3,5,1,5,8,7,9,6]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。