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. 如何做Gibbs采样(how to do gibbs-sampling)

    原文地址:<如何做Gibbs采样(how to do gibbs-sampling)> 随机模拟 随机模拟(或者统计模拟)方法最早有数学家乌拉姆提出,又称做蒙特卡洛方法.蒙特卡洛是一个著名 ...

  2. linux下 tags相关

    在vim中配置好了YouCompleteMe插件,发现把光标移动到函数名下再按ctrl+],并不能跳转到该函数的定义处.解决办法: 1.先查看有没有安装ctags,运行ctags –version查看 ...

  3. HDU--3487 Play with Chain (Splay伸展树)

    Play with Chain Problem Description YaoYao is fond of playing his chains. He has a chain containing ...

  4. Java 8 新特性终极版

    声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己 ...

  5. Hive集成HBase详解

    摘要 Hive提供了与HBase的集成,使得能够在HBase表上使用HQL语句进行查询 插入操作以及进行Join和Union等复杂查询   应用场景 1. 将ETL操作的数据存入HBase 2. HB ...

  6. PHP设计模式笔记七:观察者模式 -- Rango韩老师 http://www.imooc.com/learn/236

    观察者模式 概述: 1.观察者模式(Observer),当一个对象状态发生改变时,依赖他的对象全部会收到通知,并自动更新 2.场景:一个事件发生后,要执行一连串更新操作,传统的编程方式,就是在事件的代 ...

  7. android 点击桌面图标,打开手机浏览器进入对应的站点

    做一个假的adnroid app.要实现点击桌面图标.打开手机浏览器进入对应的站点,实现方法非常easy import android.app.Activity; import android.con ...

  8. Swift 2.0初探:值得注意的新特性

    转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度的WWDC大会如期而至,在大会上A ...

  9. IT痴汉的工作现状25-技术之养成

    要想成为技术大牛,除了天赋以外,更与后天的刻苦努力分不开.伟仔我天生愚顿.工作多年后仍与大牛相差甚远,更加觉得技术的养成是一个异常困难的过程. 是我不用功吗?我不这样觉得.伟仔尽管是个懒人,但对于技术 ...

  10. 分页搜索查询sql

    select * from (select t.*,rownum no from " + table + " t where scbj=0)where (no>(" ...