C#数据结构_基本概念及线性表
常见的4类数据结构: 1.集合。 2.线性结构。3.树形结构。4.图状结构。
数据结构(Data Structure)简记为 DS,是一个二元组,DS = (D,R)
其中:D 是数据元素的有限集合,R 是数据元素之间关系的有限集合。
数据的存储结构包括顺序存储结构和链式存储结构两种。C#语言中用数组来实现顺序存储结构。
算法的5个重要特征: 1.有穷性。2.确定性。3.可行性。4.输入。5.输出。
线性表:存在一对一的线性关系,一对一的关系指的是数据元素之间的位置关系
特点:(1)除第一个位置的数据 元素外,其它数据元素位置的前面都只有一个数据元素
(2)除最后一个位置的 数据元素外,其它数据元素位置的后面都只有一个元素
线性表(List)是由 n(n≥0)个相同类型的数据元素构成的有限序列。线性表通常记为:L=(a1,a2,…,ai-1,ai, ai+1,…,an),a1是线性 表中第一个位置的数据元素。an是线性表中最后一个位置 的数据元素,。n为线性表的表长,n=0 时的线性表被称 为空表(Empty List)。
线性表的接口如下所示。
public interface IListDS<T> { int GetLength(); //求长度 void Clear(); //清空操作 bool IsEmpty(); //判断线性表是否为空 void Append(T item); //附加操作 void Insert(T item, int i); //插入操作 T Delete(int i); //删除操作 T GetElem(int i); //取表元 int Locate(T value); //按值查找 }
线性表的顺序存储是指在内存中用一块地址连续的空间依次存放线性表的数据元素, 用这种方式存储的线性表叫顺序表(Sequence List)。顺序表的特点 是表中相邻的数据元素在内存中存储位置也相邻。数据元素占w个存储单元,设第i个数据元素的存储地址为Loc(ai),则有:Loc(ai)= Loc(a1)+(i-1)*w 1≤i≤n。
由于计算顺序表中每个数据元素存储地址的时间相同,所以顺序表 具有随机存取的特点。数组具有表示顺序表的数据存储区域的特 性。
last 表示顺序 表中最后一个数据元素在数组中的位置。如果顺序表中有数据元素时,last 的变 化范围是 0 到 maxsize-1,如果顺序表为空,last=-1
顺序表类 SeqList<T>的实现说明如下所示。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class SeqList<T> : IListDS<T> { private int maxsize; //顺序表的容量 private T[] data; //数组,用于存储顺序表中的数据元素 private int last; //指示顺序表最后一个元素的位置 //索引器 public T this[int index] { get { return data[index]; } set { data[index] = value; } } //最后一个数据元素位置属性 public int Last { get { return last; } } //容量属性 public int Maxsize { get { return maxsize; } set { maxsize = value; } } //构造器 public SeqList(int size) { data = new T[size]; maxsize = size; last = -1; } //求顺序表的长度 public int GetLength() { return last + 1; } //清空顺序表 public void Clear() { last = -1; } //判断顺序表是否为空 public bool IsEmpty() { if (last == -1) { return true; } else { return false; } } //判断顺序表是否为满 public bool IsFull() { if (last == maxsize - 1) { return true; } else { return false; } } //在顺序表的末尾添加新元素 public void Append(T item) { if (IsFull()) { System.Console.WriteLine("满了"); return; } data[++last] = item; } //在顺序表的第i位置插入一个数据元素 public void Insert(T item, int i) { if (IsFull()) { System.Console.WriteLine("满了"); return; } if (i < 1 || i> last+2) { System.Console.WriteLine("越界"); return; } if(i==last+2) { data[last+1]=item; } else { for (int j = last; j >= i - 1; --j) { data[j + 1] = data[j]; } data[i - 1] = item; } ++last; } //删除顺序表的第i个数据元素 public T Delete(int i) { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("List is empty"); return tmp; } if (i < 1 || i > last + 1) { Console.WriteLine("Position is error!"); return tmp; } if (i == last + 1) { tmp = data[last--]; } else { tmp = data[i - 1]; for (int j = i; j <= last; ++j) { data[j] = data[j + 1]; } } --last; return tmp; } //获得顺序表的第i个数据元素 public T GetElem(int i) { if (IsEmpty() || (i < 1) || (i > last + 1)) { Console.WriteLine("List is empty or Position is error!"); return default(T); } return data[i - 1]; } //在顺序表中查找值为value的数据元素 public int Locate(T value) { if (IsEmpty()) { Console.WriteLine("List is Empty!"); return -1; } int i = 0; for (i = 0; i <= last; ++i) { if (value.Equals(data[i])) { break; } } if (i > last) { return -1; } return i; } }
顺序表的倒置 算法思路:把第一个元素与最后一个元素交换,把第二个元素与倒数第二个元素交换。一般地,把第 i 个元素与第 n-i 个元素交换,i 的取值范围是 0 到 n/2(n 为顺序表的长度)。算法实现如下:
public void ReversSeqList(SeqList<int> L) { int tmp = 0; int len = L.GetLength(); for (int i = 0; i<= len/2; ++i) { tmp = L[i]; L[i] = L[len - i];
L[len - i] = tmp; } }
算法思路:依次扫描 La 和 Lb 的数据元素,比较 La 和 Lb 当前数据元素的 值,将较小值的数据元素赋给 Lc,如此直到一个顺序表被扫描完,然后将未完 的那个顺序表中余下的数据元素赋给 Lc 即可。Lc 的容量要能够容纳 La 和 Lb 两个表相加的长度。
按升序合并两个表的算法 C#实现如下:
public SeqList<int> Merge(Seqlist<int> La, SeqList<int> Lb) { SeqList<int> Lc = new SeqList<int>(La.Maxsize + Lb.Maxsize); int i = 0; int j = 0; int k = 0; //两个表中都有数据元素 while ((i <= (La.GetLength()-1))&& (j <= (Lb.GetLength()-1))) { if (La[i] <Lb[j]) { Lc.Append(La[i++]); } else { Lc.Append(Lb[j++]); } } //a表中还有数据元素 while (i <= (La.GetLength() - 1)) { Lc.Append(La[i++]); } //b表中还有数据元素 while (j <= (Lb.GetLength() - 1)) { Lc.Append(Lb[j++]); } return Lc; }
已知一个存储整数的顺序表 La,试构造顺序表 Lb,要求顺序表 Lb 中 只包含顺序表 La 中所有值不相同的数据元素
算法思路:先把顺序表 La 的第 1 个元素赋给顺序表 Lb,然后从顺序表 La 的第 2 个元素起,每一个元素与顺序表 Lb 中的每一个元素进行比较,如果不相 同,则把该元素附加到顺序表 Lb 的末尾。
public SeqList<int> Purge(SeqList<int> La) { SeqList<int> Lb = new SeqList<int>(La.Maxsize); //将a表中的第1个数据元素赋给b表 Lb.Append(La[0]); //依次处理a表中的数据元素 for (int i=1; i<=La.GetLength()-1; ++i) { int j = 0; //查看b表中有无与a表中相同的数据元素 for (j = 0; j<=Lb.GetLength()-1; ++j) { //有相同的数据元素 if (La[i].CompareTo(Lb[j]) == 0) { break; } } //没有相同的数据元素,将a表中的数据元素附加到b表的末尾。 if(j>Lb.GetLength()-1) { Lb.Append(La[i]); } } return Lb; }
链表进行插入 和删除时不需要移动数据元素,但同时也失去了顺序表可随机存储的优点
单链表结点类的实现:
public class Node<T> { private T data; //数据域 private Node<T> next; //引用域 //构造器 public Node(T val, Node<T> p) { data = val; next = p; } //构造器 public Node(Node<T> p) { next = p; } //构造器 public Node(T val) { data = val; next = null; } //构造器 public Node() { data = default(T); next = null; } //数据域属性 public T Data { get{return data;} set{ data = value; } } //引用域属性 public Node<T> Next { get { return next; } set { next = value; } } }
单链表类 LinkList<T>的实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class LinkList<T> : IListDS<T> { private Node<T> head; //单链表的头引用 //头引用属性 public Node<T> Head { get{ return head; } set{ head = value; } } //构造器 public LinkList() { head = null; } //求单链表的长度 public int GetLength() { Node<T> p = head; int len = 0; while (p != null) { ++len; p = p.Next; } return len; } //清空单链表 public void Clear() { head = null; } //判断单链表是否为空 public bool IsEmpty() { if (head == null) { return true; } else { return false; } } //在单链表的末尾添加新元素 public void Append(T item) { Node<T> q = new Node<T>(item); Node<T> p = new Node<T>(); if (head == null) { head = q; return; } p = head; while (p.Next != null) { p = p.Next; } p.Next = q; } //在单链表的第i个结点的位置前插入一个值为item的结点 public void Insert(T item, int i) { if (IsEmpty() || i < 1) { Console.WriteLine("List is empty or Position is error!"); return; } if (i == 1) { Node<T> q = new Node<T>(item); q.Next = head; head = q; return; } Node<T> p = head; Node<T> r = new Node<T>(); int j = 1; while (p.Next != null&& j < i) { r = p; p = p.Next; ++j; } if (j == i) { Node<T> q = new Node<T>(item); q.Next = p; r.Next = q; } } //在单链表的第i个结点的位置后插入一个值为item的结点 public void InsertPost(T item, int i) { if (IsEmpty() || i < 1) { Console.WriteLine("List is empty or Position is error!"); return; } if (i == 1) { Node<T> q = new Node<T>(item); q.Next = head.Next; head.Next = q; return; } Node<T> p = head; int j = 1; while (p != null&& j < i) { p = p.Next; ++j; } if (j == i) { Node<T> q = new Node<T>(item); q.Next = p.Next; p.Next = q; } } //删除单链表的第i个结点 public T Delete(int i) { if (IsEmpty()|| i < 0) { Console.WriteLine("Link is empty or Position is error!"); return default(T); } Node<T> q = new Node<T>(); if (i == 1) { q = head; head = head.Next; return q.Data; } Node<T> p = head; int j = 1; while (p.Next != null&& j < i) { ++j; q = p; p = p.Next; } if (j == i) { q.Next = p.Next; return p.Data; } else { Console.WriteLine("The ith node is not exist!"); return default(T); } } //获得单链表的第i个数据元素 public T GetElem(int i) { if (IsEmpty()) { Console.WriteLine("List is empty!"); return default(T); } Node<T> p = new Node<T>(); p = head; int j = 1; while (p.Next != null&& j < i) { ++j; p = p.Next; } if (j == i) { return p.Data; } else { Console.WriteLine("The ith node is not exist!"); return default(T); } } //在单链表中查找值为value的结点 public int Locate(T value) { if(IsEmpty()) { Console.WriteLine("List is Empty!"); return -1; } Node<T> p = new Node<T>(); p = head; int i = 1; while (!p.Data.Equals(value)&& p.Next != null) { P = p.Next; ++i; } return i; } }