using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DataStructure
{
class MySingleLinkedList<T> : MyIList<T>
{ private Node<T> head; public Node<T> Head
{
get { return head; }
set { head = value; }
} public MySingleLinkedList()
{
head = null;
} public MySingleLinkedList(Node<T> p)
{
head = p;
} /// <summary>
/// 求单链表的长度
/// 求单链表的长度与顺序表不同。顺序表可以通过指示表中最后一个数据元素的last直接求得,因为顺序表所占用的空间是连续的空间,而单链表需要从头引用开始,一个结点一个结点遍历,直到表的末尾。
/// </summary>
/// <returns></returns>
public int GetLength()
{
if (IsEmpty())
{
return 0;
}
else
{
Node<T> p = head;
int i = 1;
while (p.Next != null)
{
p = p.Next;
i++;
}
return i;
#region 人家是这么写的
//int len = 0;
//while (p != null)
//{
// ++len;
// p = p.Next;
//}
//return len;
#endregion
}
} /// <summary>
/// 清空操作
/// 清空操作是指清除单链表中的所有结点使单链表为空,此时,头引用head为null。
/// </summary>
public void Clear()
{
head = null;
} /// <summary>
/// 判断单链表是否为空
/// 如果单链表的头引用为null,则单链表为空,返回true,否则返回false。
/// 判断单链表是否为空的算法实现如下
/// </summary>
/// <returns></returns>
public bool IsEmpty()
{
if (head == null)
{
return true;
}
return false;
} /// <summary>
/// 附加操作
/// 单链表的附加操作也需要从单链表的头引用开始遍历单链表,直到单链表的末尾,然后在单链表的末端添加一个新结点。
/// </summary>
/// <param name="item"></param>
public bool Append(T item)
{
Node<T> appendItem = new Node<T>(item);
if (IsEmpty())
{
head = appendItem;
}
else
{
Node<T> theLastItem = new Node<T>();
theLastItem = head;
while (theLastItem.Next != null)
{
theLastItem = theLastItem.Next;
}
theLastItem.Next = appendItem;
}
return true;
} /// <summary>
/// 插入操作
/// 单链表的插入操作是指在表的第i个位置结点处插入一个值为item的新结点。插入操作需要从单连表的头引用开始遍历,直到找到第i个位置的结点。插入操作分为在结点之前插入的前插操作和在结点之后插入的后插操作。
/// 注意点:
/// 1插入要考虑空,满
/// 2插入要考虑输入位置是否正确
/// 3要把前继节点给具体显式声明出来,这样比较清晰!
/// 我这里做的是《前插》操作!!!!!!!!
/// </summary>
/// <param name="item"></param>
/// <param name="i"></param>
public void Insert(T item, int i)
{
int len = GetLength();
if (len == 0)
{
Console.WriteLine("单链表为空,不存在插入过程!");
}
else if (i <= 0 || i > len)
{
Console.WriteLine("你输入的位置有错误!!!");
}
else
{
//插头部(这样对于我的逻辑来说清晰一点)
if (i == 1)
{
Node<T> temp = new Node<T>();
temp = head;
head = new Node<T>(item);
head.Next = temp;
}
else
{
Node<T> p = head;
int j = 1;
while (p.Next != null)
{
if (++j == i)
{
//找到了要插入的位置的前面一个节点
Node<T> temp = new Node<T>();
temp = p.Next;
p.Next = new Node<T>(item);
p.Next.Next = temp;
//完成了插入工作,退出循环!
break;
}
p = p.Next;
}
}
}
#region 教科书的前插操作
// 前插操作
//前插操作需要查找第i个位置的结点的直接前驱。设p指向第i个位置的结点,q指向待插入的新结点,r指向p的直接前驱结点,将q插在p之前的操作如图2.8所示。如果要在第一个结点之前插入新结点,则需要把p结点的地址保存在q的引用域中,然后把p的地址保存在头引用中。
// 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;
//}
//else
//{
//Console.Writeline(“Position is error!”);
//}
//return;
//} #endregion } /// <summary>
/// 删除操作
/// 单链表的删除操作是指删除第i个结点,返回被删除结点的值。删除操作也需要从头引用开始遍历单链表,直到找到第i个位置的结点。如果i为1,则要删除第一个结点,则需要把该结点的直接后继结点的地址赋给头引用。对于其它结点,由于要删除结点,所以在遍历过程中需要保存被遍历到的结点的直接前驱,找到第i个结点后,把该结点的直接后继作为该结点的直接前驱的直接后继。删除操作如图2.10所示。
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public bool Delete(int i)
{
int len = GetLength();
if (IsEmpty())
{
Console.WriteLine("单链表为空,根本不存在删除操作");
return false;
}
else if (i <= 0 || i > len)
{
Console.WriteLine("输入的位置有误!!!!!");
return false;
}
else
{
if (i == 1)
{
head = head.Next;
}
else
{
Node<T> beforeDelete = new Node<T>();
Node<T> currentNode = new Node<T>();
currentNode = head;
int currentIndex = 1;
while (currentNode.Next != null && currentIndex < i)
{
beforeDelete = currentNode;
currentNode = currentNode.Next;
currentIndex++;
}
//这样写比较有逻辑性一点
//先通过while,找出要删除的节点之前的那一个节点
//while,只负责此逻辑功能
//不像我的《插入》写法,显得比较乱
//这点仁者见仁智者见智
beforeDelete.Next = currentNode.Next;
}
return true;
}
} /// <summary>
/// 取表元
/// 取表元运算是返回单链表中第i个结点的值。与插入操作一样,时间主要消耗在结点的遍历上。如果表为空则不进行遍历。当表非空时,i等于1遍历的结点数最少(1个),i等于n遍历的结点数最多(n个,n为单链表的长度),平均遍历的结点数为n/2。所以,取表元运算的时间复杂度为O(n)。
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public T GetElem(int i)
{
int len = GetLength();
if (IsEmpty())
{
Console.WriteLine("单链表是空的,没什么好取出来!");
return default(T);
}
if (i <= 0 || i > len)
{
Console.WriteLine("你输入的位置有误!");
return default(T);
}
else
{
Node<T> p = head;
int j = 1;
//这种循环的写法
//在单链表的操作中
//尤其常见
while (p.Next != null && j < i)
{
p = p.Next;
j++;
}
return p.Data;
}
} /// <summary>
/// 按值查找
/// 单链表中的按值查找是指在表中查找其值满足给定值的结点。由于单链表的存储空间是非连续的,所以,单链表的按值查找只能从头引用开始遍历,依次将被遍历到的结点的值与给定值比较,如果相等,则返回在单序表中首次出现与给定值相等的数据元素的序号,称为查找成功;否则,在单链表中没有值与给定值匹配的结点,返回一个特殊值表示查找失败。
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public int Locate(T value)
{
bool haveFound = false;
Node<T> p = new Node<T>();
p = head;
int j = 1;
while (p.Next != null)
{
if (p.Data.Equals(value))
{
haveFound = true;
break;
}
p = p.Next;
j++;
}
if (haveFound)
return j;
else
return -1;
#region 教科书错误的写法,如果没有找到,会返回最后一个元素的index
// 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;
//}
#endregion
}
} public class Node<T>
{ private Node<T> next; public Node<T> Next
{
get { return next; }
set { next = value; }
} private T data; public T Data
{
get { return data; }
set { data = value; }
} public Node(T t)
{
data = t;
next = null;
} public Node()
{
// TODO: Complete member initialization
next = null;
}
}
}

数据结构之单链表,c#实现的更多相关文章

  1. Python数据结构之单链表

    Python数据结构之单链表 单链表有后继结点,无前继结点. 以下实现: 创建单链表 打印单链表 获取单链表的长度 判断单链表是否为空 在单链表后插入数据 获取单链表指定位置的数据 获取单链表指定元素 ...

  2. javascript数据结构之单链表

    下面是用javascript实现的单链表,但是在输出的时候insert方法中存在问题,chrome的console报错说不能读取空的属性,调试了很久都没有通过,先在这里存着,以后再来修改一下. //数 ...

  3. 数据结构之单链表的实现-java

    一.单链表基本概念 单链表是一种链式存取的数据结构,用一组地址任意的存储单元(一般是非连续存储单元)存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点的构成:元素data + 指针next ...

  4. python 数据结构之单链表的实现

    链表的定义: 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址.由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就 ...

  5. 数据结构(一) 单链表的实现-JAVA

    数据结构还是很重要的,就算不是那种很牛逼的,但起码得知道基础的东西,这一系列就算是复习一下以前学过的数据结构和填补自己在这一块的知识的空缺.加油.珍惜校园中自由学习的时光.按照链表.栈.队列.排序.数 ...

  6. 数据结构 - 静态单链表的实行(C语言)

    静态单链表的实现 1 静态链表定义 静态链表存储结构的定义如下: /* 线性表的静态链表存储结构 */ #define MAXSIZE 1000 /* 假设链表的最大长度是1000 */ typede ...

  7. 数据结构 - 动态单链表的实行(C语言)

    动态单链表的实现 1 单链表存储结构代码描述 若链表没有头结点,则头指针是指向第一个结点的指针. 若链表有头结点,则头指针是指向头结点的指针. 空链表的示意图: 带有头结点的单链表: 不带头结点的单链 ...

  8. 【数据结构】单链表介绍及leetcode206题反转单链表python实现

    题目传送门:https://leetcode-cn.com/problems/reverse-linked-list/ 文章目录 单链表介绍 链表 概念 种类 优缺点 单链表(slist) leetc ...

  9. 数据结构(2):单链表学习使用java实现

    单链表是单向链表,它指向一个位置: 单链表常用使用场景:根据序号排序,然后存储起来. 代码Demo: package com.Exercise.DataStructure_Algorithm.Sing ...

  10. 数据结构:单链表结构字符串(python版)添加了三个新功能

    #!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...

随机推荐

  1. Json帮助类以及如何使用

    首先要添加引用System.Runtime.Serialization. public class JSONHelper { public static string Serialize<T&g ...

  2. hdu2460-Network:边的双连通分量

    题目大意:给出一个无向图以及Q次询问,每次询问增加一条无向边,要求输出增加这条边后剩余的桥的数目. 算法:类似于求割点的方法,先做一次dfs求出所有的桥,并且维护这棵dfs树,当一次询问加入一条边(a ...

  3. 第27讲 UI组件之 ScrollView与底部动态添加数据

    第27讲 UI组件之 ScrollView与底部动态添加数据 1. ScrollView(滚动视图) ScrollView(滚动视图)是实现滚动的一个控件,只需要将需要滚动的控件添加到ScrollVi ...

  4. 一个不错的PPT,扁平化设计,开放资源,要的进来

    开了那么多的博客,没做啥资源贡献,今天共享一个不错的PPT模板.例如以下图所看到的,须要的话留下邮箱 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGFp ...

  5. windows下删除服务的方法

    删除的办法有两个: 办法一: 用sc.exe这个Windows命令 开始——运行——cmd.exe,然后输入sc就可以看到了.使用办法很简单: sc delete "服务名" (如 ...

  6. [计算机组成原理][实验十.R-I-J型指令CPU设计实验总结]

    总算解决一大心头之患了,比想象中容易,通宵两夜,刷完了十个实验,这个实验就是最后的了.感慨颇多.特地写篇总结. 想做一件事,就立马去做把.你会发现没那么困难,往往最大的困难,是心里的困难. 培养了HD ...

  7. DevExpress控件-GridControl根据条件改变单元格/行颜色--转载

    DevExpress控件-数据控件GridControl,有时我们需要根据特定条件改变符合条件的行或者单元格颜色达到突出显示目的,现在动起鼠标跟我一起操作吧,对的,要达到这个目的您甚至都不用动键盘. ...

  8. Sqlserver统计语句

    --查看被缓存的查询计划 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED st.text AS [SQL] , cp.cacheobjtype , c ...

  9. GDI+编程的10个基本技巧(转)

    创建绘图表面 创建绘图表面有两种常用的方法.下面设法得到PictureBox的绘图表面. private void Form1_Load(object sender, System.EventArgs ...

  10. Java的Object对象

    Object对象是除了基础对象之外,所有的对象都需要继承的父对象,包括数组也继承了Object Object里面的关键函数罗列如下: clone();调用该函数需要实现 Cloneable,否则会抛出 ...