目录
一、简介
二、方法
2.1 建立Vector类
2.2 Vector成员
2.3 Vector属性
2.4 Vector方法
2.4.1 构造函数
2.4.2 Vector元素操作方法
2.4.3 Vector 运算
三、调用方法
3.1 方法
3.1.1 Append
3.1.2 this[]
3.1.3 Insert
3.1.4 DelLen
3.1.5 FindNumber
3.1.6 Find
3.1.7 LookUp
3.1.8 Data
3.1.9 Copy
3.1.10 Sum
3.1.11 Mean
3.1.12 Max
3.1.12 Min
3.1.12 Sort
3.2 运算符
3.2.1 + 正号
3.2.2 - 负号
3.2.3 + 加法
3.2.4 – 减法
3.2.5 乘法
四、验证
4.1 验证代码
4.2 验证结果:
一、简介
上一篇博客中描述了如何写一个Vector类,然而所写的Vector类仅限于double型,无法满足实际工作需求。因此在上一篇文档基础上,撰写本文,介绍如何书写一个泛型Vector,可以应用于int、double、float等C#数值型的Vector。
本博客所描述的Vector<T>是一个泛型,具有不同数值类型Vector向量构造、新增、删除、查询、更改、深度复制、显示元素值、vector运算、排序等功能。整体代码如下所示。
注:上一篇博客旨在讲解如何利用C#写一个自己的类,第一步写什么,第二步写什么,因此采用写专利的方式编写博客,而本博客,是编写方式是与上一篇博客的方式是一样的,因此不再以写专利的方式写博客,而是以写文章的方式书写。博客中描述不清楚的,可以在评论区留下你的问题,我将针对你的问题,进行讲解。
注:本文中Vector表示向量的类,vetcor表示具体的向量。
二、方法
2.1 建立Vector<T>类
sing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XMU//.Base
{
/// <summary>
/// 类:向量类,存放向量的定义,以及向量的一些操作和算法;
/// </summary>
internal class Vector<T> where T : struct
{
}
}
注:<T> where T : struct中,T表示泛型,是一个占位符,可以表示C#任何数据类型,包括自定义的类型,where T : struct 表示泛型的约束,约束泛型的类型为struct,及数值型。
2.2 Vector成员
Vector成员只包含一个存储数据的T[]型_data成员字段,代码如下:
/// <summary>
/// Vector成员定义:定义数据成员
/// </summary>
private T[] _data;
2.3 Vector属性
Vector只包含一个记录Vector向量长度Length的属性,具体代码如下:
/// <summary>
/// Vector属性定义:定义向量的长度属性
/// </summary>
public int Length => _data.Length;
2.4 Vector方法
本文撰写的Vector类方法主要分为两种,一种是向量Vector<T>的构造;一种是vector元素之间的操作,具体包括vector的增、删、改、查、复制、求和、求最大值、求最小值、求均值、排序;最后一种是vector加减乘除的运算。
2.4.1 构造函数
本文所写的Vector构造函数有三种类型:构造空的vector、根据指定长度构造全0或全1 vector、根据数组构造vector,具体代码如下:
#region 构造函数/方法
/// <summary>
/// Vector构造函数:空Vector构造
/// </summary>
public Vector()
{
_data = new T[0];
}
/// <summary>
/// Vectot构造:根据长度来构造全0或全1Vector,默认为全 0 Vector
/// </summary>
/// <param name="length">Vector长度</param>
/// <param name="fillOne">可选:布尔值,是否为全1Vector,默认为false,表示全0true表示全 1 Vector;</param>
public Vector(int length, bool fillOne = false)
{
_data = new T[length];
if (fillOne)
{
for (int i = 0; i < length; i++)
{
_data[i] = (dynamic)1;
}
}
}
/// <summary>
/// Vector构造:根据T类型数组元素,构造(复制)一个Vector
/// </summary>
/// <param name="values">T 类型的数组,至少2个元素的数组</param>
public Vector(params T[] values)
{
// 新建一个等大的容器,用于存放数据
_data = new T[values.Length];
// 将值写入到Vector中
Array.Copy(values, _data, values.Length);
}
#endregion
为了便于显示vector元素,验证代码正确性,建议优先重写Tostring方法,具体代码如下:
/// <summary>
/// Vector方法:重写Vector显示方法
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "[" + string.Join(", ", _data) + "]";
}
2.4.2 Vector元素操作方法
Append
Append方法可以在vector新增一个同类型的数或另一个vector,具体代码如下(无返回值):
/// <summary>
/// Vector 新增元素
/// </summary>
/// <param name="values">需要新增的T数组values</param>
/// <returns></returns>
public void Append(params T[] values)
{
Vector<T> v = new Vector<T>(Length + values.Length);
// 元素写入
Array.Copy(_data, v._data, Length);
// 插入元素写入
Array.Copy(values, 0, v._data, Length, values.Length);
_data = v._data;
}
/// <summary>
/// Vector 新增元素
/// </summary>
/// <param name="v1">需要新增的Vextor向量</param>
/// <returns></returns>
public void Append(Vector<T> v1)
{
Vector<T> v = new Vector<T>(Length + v1.Length);
// 元素写入
Array.Copy(_data, v._data, Length);
// 插入的元素写入
Array.Copy(v1._data, 0, v._data, Length, v1._data.Length);
_data = v._data;
}
this[]
this[] 可以根据中括号内的索引值,查询对应位置的元素,具体代码如下:
/// <summary>
/// Vectot 元素查询和更改
/// </summary>
/// <param name="index">查询或更改的位置(索引)</param>
/// <returns></returns>
public T this[int index]
{
get => _data[index]; // 查询
set => _data[index] = value; // 更改元素值
}
Insert
Insert方法可以在vector中任何位置插入同类型的数或vector向量,若不指定位置,则在末尾插入,具体代码如下(无返回值):
/// <summary>
/// Vextor Vector1中插入另一个Vector2;
/// 如果是数组,需将数组通过Vector构造函数构造成Vector类型数据。
/// </summary>
/// <param name="v1">需要插入的Vector</param>
/// <param name="indexInsert">可选:插入的位置,
/// 默认indexInsert=-1,表示在末尾,indexInsert 必须大于-1</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public Vector<T> Insert(Vector<T> v1, int indexInsert = -1)
{
if (indexInsert < -1)
{
throw new Exception("输入的索引错误,请从新输入");
}
if (indexInsert > Length || indexInsert == -1)
{
indexInsert = Length;
}
Vector<T> v = new Vector<T>(Length + v1.Length);
// 值拷贝到容器中
Array.Copy(_data, v._data, indexInsert);
Array.Copy(v1._data, 0, v._data, indexInsert, v1.Length);
Array.Copy(_data, indexInsert, v._data, indexInsert + v1.Length, Length - indexInsert);
return v;
}
当然,插入操作,可以没有必要有输出值,因此建议写成下面的代码。
public void Insert(Vector<T> v1, int indexInsert = -1)
{
if (indexInsert < -1)
{
throw new Exception("输入的索引错误,请从新输入");
}
if (indexInsert > Length || indexInsert == -1)
{
indexInsert = Length;
}
Vector<T> v = new Vector<T>(Length + v1.Length);
// 值拷贝到容器中
Array.Copy(_data, v._data, indexInsert);
Array.Copy(v1._data, 0, v._data, indexInsert, v1.Length);
Array.Copy(_data, indexInsert, v._data, indexInsert + v1.Length, Length - indexInsert);
_data = v._data;
}
DelteLen
DelteLen方法可以删除vector中任何指定位置、指定长度(默认为1)的连续元素,具体代码如下(无返回值):
/// <summary>
/// Vector 删除指定位置后指定长度,默认长度为1
/// </summary>
/// <param name="startIndex">需要删除元素的第一个位置</param>
/// <param name="delLen">可选:删除连续元素的个数,默认为1</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public void DelteLen(int startIndex, int delLen = 1)
{
if (startIndex < 0 || startIndex > Length - 1 || delLen < 1)
{
throw new Exception("输入的索引或删除的长度有误,请重新输入");
}
// 防止长度和索引之和大于Vector的长度
if (delLen + startIndex > Length)
{
delLen = Length - startIndex;
}
// 空的容器
Vector<T> v = new Vector<T>(Length - delLen);
// 写入1
Array.Copy(_data, v._data, Length - startIndex - delLen);
// 写入2
Array.Copy(_data, startIndex + delLen, v._data, startIndex, Length - startIndex - delLen);
_data = v._data;
}
FindNumber
FindNumber方法可以查询vector中元素为某一个值的个数,具体代码如下:
/// <summary>
/// Vector 查询vector某一个元素的个数
/// </summary>
/// <param name="value">所要查询的值</param>
/// <returns>返回所查值的个数</returns>
public int FindNumber(T value)
{
// 统计个数
int count = 0;
for (int i = 0; i < Length; i++)
{
if (_data[i] == (dynamic)value)
{
count++;
}
}
return count; //元素的个数
}
Find
Find方法可以查询元素为某一个值的所有位置,具体代码如下:
/// <summary>
/// Vector 查询元素的位置
/// </summary>
/// <param name="value">索要查询的值</param>
/// <returns>返回查询结果位置的索引数据</returns>
public int[] Find(T value)
{
// 首先统计个数
int count = this.FindNumber(value);
// 根据个数,建立容器
int[] indexs = new int[count];
int index = 0; // 用于表示indexs的索引
for (int i = 0; i < Length; i++)
{
if (_data[i] == (dynamic)value)
{
indexs[index] = i;
index++;
}
}
return indexs;
}
限于篇幅考虑接下来Vector<T>类公布代码,可根据《第三章、方法调用》中方法的函数介绍,编写相关代码。完整代码可以到我的博客中下载。
LookUp
LookUp方法是用来查询vector元素等于value值的所有位置索引int数组,具体代码如下:略
Data
Data方法可以用来提取vector向量元素,或则说是量T 类型的vector 转化为T类型的数组,具体如下:略
Copy
Copy方法可以深度复制一个全新的vector,具体代码如下:略
Sum
Sum方法是用来计算vector中所有元素的和,具体代码如下:略
Mean
Mean方法可用来计算vector所有元素的平均值,具体如下:略
Max
Max方法是用来找出vector中最大的元素值。
Min
Min方法是用来找出vector中最小的元素值。
Sort
Sort方法是用来排序,默认从小到大排序。
2.4.3 Vector 运算
+正号
+正号运算符值用来返回一个全新的vector,具体代码如下:
/// <summary>
/// Vector "+" 正号运算符重载
/// </summary>
/// <param name="v1"></param>
/// <returns></returns>
public static Vector<T> operator +(Vector<T> v)
{
return v.Copy();
}
-负号
-负号运算符是用来返回一个原先vector的相反向量,有返回值,具体代码如下:
/// <summary>
/// Vector "-"负号运算符重载
/// </summary>
/// <param name="v">需要重载的Vector</param>
/// <returns>重载后新的Vector</returns>
public static Vector<T> operator -(Vector<T> v)
{
Vector<T> v1 = new Vector<T>(v.Length);
for (int i = 0; i < v1.Length; i++)
{
v1[i] = -(dynamic)v[i];
}
return v1;
}
+加法
+加法运算符是用来计算vector与一个数或者另一个vector相加,具体代码如下:
/// <summary>
/// Vector "+"加法运算符重载,Vector和Vector相加
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static Vector<T> operator +(Vector<T> v1, Vector<T> v2)
{
// 维度比较
if (v1.Length != v2.Length)
{
throw new Exception("维度不一致,无法相加");
}
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = (dynamic)v1[i] + v2[i];
}
return v;
}
/// <summary>
/// Vector "+"加法运算符重载,Vector和一个常数相加
/// </summary>
/// <param name="v1"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Vector<T> operator +(Vector<T> v1, T value)
{
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = (dynamic)v1[i] + value;
}
return v;
}
/// <summary>
/// Vector "+"加法运算符重载,Vector和一个常数相加
/// </summary>
/// <param name="v1"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Vector<T> operator +(T value, Vector<T> v1)
{
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = (dynamic)v1[i] + value;
}
return v;
}
注:有三种情况,vector1+ vector2、vector+value、value+vector,所以+加法重载了3次。
-减法
+加法运算符是用来计算vector与一个数或者另一个vector相减,具体代码如下:
/// <summary>
/// Vector "-"减法运算符重载,Vector1 -Vector2
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static Vector<T> operator -(Vector<T> v1, Vector<T> v2)
{
// 维度比较
if (v1.Length != v2.Length)
{
throw new Exception("维度不一致,无法相减");
}
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = (dynamic)v1[i] - v2[i];
}
return v;
}
/// <summary>
/// Vector "-"减法运算符重载,Vector 减去一个常数
/// </summary>
/// <param name="v1"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Vector<T> operator -(Vector<T> v1, T value)
{
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = (dynamic)v1[i] - value;
}
return v;
}
/// <summary>
/// Vector "-"减法运算符重载,常数减去Vector
/// </summary>
/// <param name="v1"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Vector<T> operator -(T value, Vector<T> v1)
{
// 新建容器
Vector<T> v = new Vector<T>(v1.Length);
for (int i = 0; i < v1.Length; i++)
{
v[i] = value - (dynamic)v1[i];
}
return v;
}
注:有三种情况,vector1-vector2、vector-value、value-vector,所以-*减法重载了3次。
*乘法
*乘法运算符用来计算vector与一个数或者另一个vector相乘,具体代码如下:略。
注:同理*乘法也重载了3次。
注:由于vector中,可能存在元素为0情况,因此本文就不在重载除法/。
注:此外,还有>、<、>=、<=、!=、|运算符重载,本博客就不在叙述。
三、调用方法
3.1 方法
3.1.1 Append
函数原型:
public void Append(Vector<T> v1)
public void Append(params T[] values)
函数说明:该方法是用来在vector末尾添加元素(可以是一个数,也可以是一个vector)。
名称 | 说明 |
v1 | 用来新增的vector |
value | 用来新增的数 |
3.1.2 this[]
this确切来说,是Vector的属性。
定义原型
public T this[int index]
名称 | 说明 |
index | 所查询的索引,int型 |
3.1.3 Insert
函数原型
public void Insert(Vector<T> v1, int indexInsert = -1)
函数说明:在vector插入另一个vector,如果是想插入数组,可以利用构造函数,将数组构造成vector,在执行插入操作。
限于篇幅,参数说明不在具体介绍。
3.1.4 DelLen
函数原型:
public void DelteLen(int startIndex, int delLen = 1)
函数说明:根据提供的删除元素起点位置startIndex和删除元素的个数(长度delLen,默认为1),无返回值。
3.1.5 FindNumber
函数原型:
public int FindNumber(T value)
函数说明:查询vector中元素等于value的个数。
3.1.6 Find
函数原型:
public int[] Find(T value)
函数说明:查询vector中元素等于value的所有位置索引,返回一个int[]数组。
3.1.7 LookUp
函数原型:
public Vector<T> LookUp(int[] indexs)
函数说明:根据索引int[]型数组,查询(提取)对应位置的所有元素。
3.1.8 Data
函数原型:
public T[] Data()
函数说明:将Vector元素提取出来,保存在T[]数组上。
3.1.9 Copy
函数原型:
public Vector<T> Copy()
函数说明:深度复制一个vector。
3.1.10 Sum
函数原型:
public T Sum()
函数说明:计算vector所有元素的总和。
3.1.11 Mean
函数原型:
public T Mean()
函数说明:用来计算vector所有元素的平均值。
3.1.12 Max
函数原型:
public T Max()
函数说明:寻找vector中最大值
3.1.12 Min
函数原型:
public T Min()
函数说明:寻找vector中最小值
3.1.12 Sort
函数原型:
public void sort(bool reverse = false)
函数说明:用来将vector进行排序,无返回值。
3.2 运算符
3.2.1 + 正号
函数原型:
public static Vector<T> operator +(Vector<T> v)
函数说明:用来重载正号运算符。
3.2.2 - 负号
函数原型:
public static Vector<T> operator -(Vector<T> v)
函数说明:用来重载负号运算符
3.2.3 + 加法
函数原型:
public static Vector<T> operator +(Vector<T> v1, Vector<T> v2)
public static Vector<T> operator +(Vector<T> v1, T value)
public static Vector<T> operator +(T value, Vector<T> v1)
函数说明:用来重载加法运算符
3.2.4 – 减法
函数原型:
public static Vector<T> operator -(Vector<T> v1, Vector<T> v2)
public static Vector<T> operator -(Vector<T> v1, T value)
public static Vector<T> operator -(T value, Vector<T> v1)
函数说明:用来重载减法运算符
3.2.5 乘法
函数原型:
public static Vector<T> operator *(Vector<T> v1, Vector<T> v2)
public static Vector<T> operator *(Vector<T> v1, T value)
public static Vector<T> operator *(T value, Vector<T> v1)
四、验证
4.1 验证代码
验证代码如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XMU
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Vector类验证, hulz");
// Vector 定义和实例化 空Vector
Vector<int> v1 = new Vector<int>();
Console.WriteLine("int-空Vector" + v1);
Vector<double> v2 = new Vector<double>(5);
Console.WriteLine("double-全 0 Vector" + v2);
Vector<double> v3 = new Vector<double>(5, true);
Console.WriteLine("double-全 1 Vector" + v3);
Vector<float> v4 = new Vector<float>(1, 2, 3, 4, 5, 6);
Console.WriteLine("根据数组构造Vector" + v4);
// 查询Vector元素
Console.WriteLine("查询Vector:" + v4[3]);
// 更改Vector元素
v4[3] = 0f;
Console.WriteLine("更改后Vector:" + v4);
// Vector 新增方法Append
Vector<int> v5 = new Vector<int>(1, 2, 3, 4);
Vector<int> v6 = new Vector<int>(5, 6, 7);
v5.Append(v6);
Console.WriteLine("Vector方法:Append新增Vextor后的效果" + v5);
v5.Append(5, 6, 7);
Console.WriteLine("Vector方法:Append新增T数组后的效果" + v5);
// 插入
Console.WriteLine("原Vector:" + v5 + "需要插入的Vector" + v6 + "插入的位置");
v5.Insert(v6);
Console.WriteLine("插入后的效果1:" + v5);
v5.Insert(v6, 2);
Console.WriteLine("插入后的效果2:" + v5);
// 删除元素
Console.WriteLine("最初Vector:" + v5);
v5.DelteLen(2);
Console.WriteLine("删除元素后的效果1:" + v5);
v5.DelteLen(0, 2);
Console.WriteLine("删除元素后的效果2:" + v5); // 当删除长度过长,将默认删除到最后一位
// 查询元素个数和位置
Vector<int> v7 = new Vector<int>(1, 2, 3, 2, 3, 2, 3, 2, 1, 2, 1);
Console.WriteLine("Vecctor:" + v7);
Console.WriteLine("Vector 统计元素2的个数:" + v7.FindNumber(2));
// 查询元素索引位置
Vector<int> indexs = new Vector<int>(v7.Find(2));
Console.WriteLine("Vector 统计元素2的位置" + indexs);
// 提取Vector所有元素,或则说将Vector转化为T[]
int[] data = v7.Data();
foreach (int temp in data) Console.Write(temp); // 打印T[]所有元素
Console.Write("\n");
// Vector 深度复制Vector
Vector<int> v8 = v7.Copy();
v8[1] = 9;
Console.WriteLine("被复制的Vector" + v7);
Console.WriteLine("复制修改后的Vector" + v8);
// "+" 正号运算符重载
Console.WriteLine("正号运算符重载Vector" + (+v7));
// "-"负号运算符重载
Console.WriteLine("负号运算符重载" + (-v7));
// Vector加法运算符重载
Console.WriteLine("加法运算符重载" + (v7 + 5));
Console.WriteLine("加法运算符重载" + (5 + v7));
Console.WriteLine("加法运算符重载" + (v7 + v8));
// Vector减法运算符重载
Console.WriteLine("减法运算符重载" + (v7 - 5));
Console.WriteLine("减法运算符重载" + (5 - v7));
Console.WriteLine("减法运算符重载" + (v7 - v8));
// Vectorc除法运算符重载,最好别写除法运算符重载,因为存在分母为0 的情况
// Vector 求和、均值、最大值
Console.WriteLine("Vector求和" + v7.Sum());
Console.WriteLine("Vector均值" + v7.Mean());
Console.WriteLine("Vector最大值" + v8.Max());
Console.WriteLine("Vector最小值" + v8.Min());
// 很具索引(int[]数组)查询对应位置中Vector元素
int[] indexs1 = { 1, 2, 19, 3, 4 };
Console.WriteLine("Vector" + v8);
Console.WriteLine("根据索引int[]数组,查找Vector对应位置的元素" + v8.LookUp(indexs1));
排序, 反向排序核心代码来自https://blog.csdn.net/beijinghorn/article/details/124151190
//v7.sort();
//Console.WriteLine("Vector排序" + v7);
//v8.sort(true);
//Console.WriteLine("Vector排序" + v8);
Console.ReadKey();
}
}
}
4.2 验证结果:
运行结果如下所示:
完整代码—>点击下载
不足之处,敬请斧正!
路漫漫其修远兮,吾将上下而求索!