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. 一、mysql分表简单介绍

    一.Mysql分表的原因 1.当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了. 分表的目的就在于此,减小数据库的负担,缩短查询时间. 2.mysql中 ...

  2. Linux磁盘及文件系统管理 2---- 使用fdisk进行磁盘管理

    1 FDISK分区工具 1 fsidk是来自IBM的分区工具,支持绝大多数的操作系统,几乎所有的Linux都装有fdisk 2 fdisk是一个支持MBR的分区工具,如果要使用GPT的话我们无法使用f ...

  3. c++之命名空间namespace

    1命名空间解决全局变量的冲突 main.h文件 #pragma once // data命名空间的名称 namespace data { ;//外部全局变量冲突 } main.cpp #include ...

  4. AngularJs学习笔记1——入门知识

    1.什么是AngularJs          AngularJs 诞生于2009年,由Misko Hevery 等人创建,后被Google收购,是一个优秀的Js框架,用于SPA(single pag ...

  5. 寒哥细谈之AutoLayout全解

    文/南栀倾寒(简书作者)原文链接:http://www.jianshu.com/p/683fbcbfb705著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 看到群中好多朋友还停留在Fr ...

  6. Linux下找不到动态链接库

    1.生成静态库 生成静态库使用ar工具,其实ar是archive的意思 $ar cqs libhello.a hello.o 2.生成动态库 用gcc来完成,由于可能存在多个版本,因此通常指定版本号: ...

  7. [Android算法] bitmap 将图片压缩到指定的大小

    Bitmap压缩到指定大小: private void imageZoom() {//图片允许最大空间 单位:KBdouble maxSize =400.00;//将bitmap放至数组中,意在bit ...

  8. javascript将毫秒还原为可读时间格式

    <script type="text/javascript"> //随便设置一个时间 var otime = new Date("2015-11-11 20: ...

  9. HDU 5903 - Square Distance [ DP ] ( BestCoder Round #87 1002 )

    题意: 给一个字符串t ,求与这个序列刚好有m个位置字符不同的由两个相同的串拼接起来的字符串 s, 要求字典序最小的答案    分析: 把字符串折半,分成0 - n/2-1 和 n/2 - n-1 d ...

  10. Light oj 1030 二分查找

    1088 - Points in Segments   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...