艾伟_转载:C#版数据结构之--线性表的链式存储(单链表)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 1.单链表的定义和由来:  链表是用一组地址可能连续也可能不连续的存储单元来存储线性表中的数据元素,在存储数据元素时,除了要存储数据元素本身之外,还要存储与它相邻的数据元素的地址信息,这两部分组成了线性表中一个数据元素的映像,称之为"结点",存储数据元素本身的部分称之为:数据域,存储相邻数据元素地...

1.单链表的定义和由来:

  链表是用一组地址可能连续也可能不连续的存储单元来存储线性表中的数据元素,在存储数据元素时,除了要存储数据元素本身之外,还要存储与它相邻的数据元素的地址信息,这两部分组成了线性表中一个数据元素的映像,称之为"结点",存储数据元素本身的部分称之为:数据域,存储相邻数据元素地址的部分称之为:地址域,所有节点通过地址域链接起来,像一个链条,故用此种方式存储的线性表称之为:链表.如果节点的地址域只存储了数据元素的直接后继的存储地址,则称这种链表为:单链表.

  与数序表相比,链表由于是通过存储后继结点地址的方式来体现线性关系的,向链表中插入,删除数据元素要比顺序表要快(因为顺序表对数据元素的插入和删除操作时,大部分情况下,要对数据元素在存储单元中做移动);但是查找链表中的数据元素要比顺序表中的查找要慢,因为查找链表中的数据元素,需要遍历链表(而顺序表由于每个元素与第一个元素的地址相对固定,所以只要知道第一个数据元素的地址和数据元素的数据类型,很快就会直接定位到要查找的数据元素).

  结点:    

      

2.单链表的实现:

2.1结点:

Node
public class Node<T>
    {
        
private T _data;

        
public T Data
        {
            
get { return _data; }
            
set { _data = value; }
        }
        
private Node<T> _next;

        
public Node<T> Next
        {
            
get { return _next; }
            
set { _next = value; }
        }

        
public Node()
        {
            _data 
= default(T);
            _next 
= null;
        }

        
public Node(T data)
        {
            _data 
= data;
            _next 
= null;
        }

        
public Node(Node<T> next)
        {
            _next 
= next;
        }

    }

2.2单链表:

SepLinkedList
  public class SepLinkedList<T>
    {
        
        
private Node<T> _head;
        
/// 
        
/// 头指针
        
/// 
        public Node<T> Head
        {
            
get { return _head; }
            
set { _head = value; }
        }

     
        
/// 
        
/// 获取单链表长度
        
/// 
        
/// 
        public int GetLength()
        {
            Node
<T> p = _head;
            
int length = 0;
            
while (p != null)
            {
                length
++;
                p 
= p.Next;
            }
            
return length;
        }

        
/// 
        
/// 清空单链表
        
/// 
        public void Clear()
        {
            _head 
= null;
        }

        
public bool IsEmpty()
        {
            
if (_head == null)
            {
                
return true;
            }
            
else
            {
                
return false;
            }
        }
        
/// 
        
/// 附件数据元素
        
/// 
        
/// 
        public void Append(T item)
        {
            Node
<T> p = new Node<T>();
            Node
<T> q = new Node<T>(item);
            
if (_head == null)
            {
                _head 
= q;
                
return;
            }
            p 
= _head;
            
while (p.Next != null)
            {
                p 
= p.Next;
            }
            p.Next 
= q;
            
        }
        
/// 
        
/// 删除第i个数据元素
        
/// 
        
/// 
        
/// 
        public T Delete(int i)
        {
            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(
"该位置不存在结点");
                
return default(T);

            }
        }
        
/// 
        
/// 在第i个位置前插入数据元素
        
/// 
        
/// 
        
/// 
        public void Insert(T item, int i)
        {
            
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;
            }
            
if (j == i)
            {
                Node
<T> q = new Node<T>(item);
                q.Next 
= p;
                r.Next 
= q;
            }
        }

        
/// 
        
/// 在第i个位置后插入一个数据元素
        
/// 
        
/// 
        
/// 
        public void InsertPost(T item, int i)
        {
            Node
<T> p = _head;
            
            
int j = 1;
            
//找第i个元素
            while (p.Next != null && j < i)
            {
                p 
= p.Next; 
                j
++;
            }

            
if (j == i)
            {
                Node
<T> q = new Node<T>(item);
                q.Next 
= p.Next;
                p.Next 
= q;
            }

        }

        
/// 
        
/// 取表元
        
/// 
        
/// 
        
/// 
        public T GetElem(int i)
        {
            
if (IsEmpty())
            {
                Console.WriteLine(
"链表为空");
                
return default(T);
            }
            Node
<T> p = new Node<T>();
            p 
= _head;
            
int j = 1;
            
while (p.Next != null && j < i)
            {
                p 
= p.Next;
                j
++;
            }
            
if (j == i)
            {
                
return p.Data;
            }
            
else
            {
                Console.WriteLine(
"未找到该序号的结点");
                
return default(T);
            }

        }
        
/// 
        
/// 按值查找数据元素
        
/// 
        
/// 
        
/// 
        public int Locate(T item)
        {
            
if (IsEmpty())
            {
                Console.WriteLine(
"链表为空");
                
return -1;
            }
            Node
<T> p = new Node<T>();
            p 
= _head;
            
int i = 1;
            
while ( p != null && !item.Equals(p.Data))
            {
                p 
= p.Next;
                i
++;
            }
            
if (p != null)
            {
                
return i;
            }
            
else
            {
                Console.WriteLine(
"单链表中不存在指定数据元素");
                
return -1;
            }
            


        }
}

 

  2.2.1插入数据元素的图示:

    

  2.2.2删除数据元素的图示:

      

  2.2.3 单链表的建立:

  第一种方式:(采用从尾部加入结点的方式)

CreateLinkedList
 /// 
        
/// 建立单链表
        
/// 
        
/// 
        static SepLinkedList<int> CreateLinkedList()
        {
            SepLinkedList
<int> result = new SepLinkedList<int>();
            Node
<int> r = new Node<int>();
            r 
= result.Head;
            
int elem = Int32.Parse(Console.ReadLine());
            
while (elem != -1)//以-1做为结束标志
            {
                Node
<int> p = new Node<int>(elem);
                
if (result.Head == null)
                {
                    result.Head 
= p;
                }
                
else
                {
                    r.Next 
= p;//加入链表
                }
                r 
= p; //记下最后一个结点
                elem = Int32.Parse(Console.ReadLine());
            }
            
if (r != null)
            {
                r.Next 
= null;//最后一个节点地址域置空
            }
            
return result;
        }

   第二种方式:(采用在头部加入结点的方式)

CreateLinkedList
  static SepLinkedList<int> CreateSepLinkedList()
        {
            SepLinkedList
<int> result = new SepLinkedList<int>();

            
int d = Int32.Parse(Console.ReadLine());
            
while (d != -1)
            {
                Node
<int> elem = new Node<int>(d);
                elem.Next 
= result.Head;
                result.Head 
= elem;
                d 
= Int32.Parse(Console.ReadLine());
            }
            
return result;
        }

2.2.4关于单链表的操作:

Code
/// <summary>
/// 将整形顺序表A中大于零的元素放入顺序表B中,把小于零的数据元素放入顺序表C中
/// 算法思想:遍历单链表la,依次读取数据元素与0比较,将小于0的数据元素放入lc,将大于0的放入lb
/// </summary>
/// <param name="la"></param>
static void PurgeToTwo(SepLinkedList<int> la,SepLinkedList<int> lb,SepLinkedList<int> lc)
{
Node
<int> p = la.Head;
while (p != null)
{
if (p.Data > 0)
lb.Append(p.Data);
else
lc.Append(p.Data);
p
= p.Next;
}
}
/// <summary>
/// 取单链表中最小值
/// 算法思想:去取最大值相反
/// </summary>
/// <param name="la"></param>
/// <returns></returns>
static int GetMin(SepLinkedList<int> la)
{
Node
<int> p = la.Head;
Node
<int> temp = p;
while (p.Next != null)
{
p
= p.Next;
if (temp.Data > p.Data)
{
temp
= p;
}
}
return temp.Data;
}
/// <summary>
/// 取单链表中最大值
/// 算法思想:取链表中的第一个数据元素,然后让这个元素与剩下的元素比较,将两者较小者存入结果中
/// </summary>
/// <param name="la"></param>
/// <returns></returns>
static int GetMax(SepLinkedList<int> la)
{
Node
<int> p = la.Head;
Node
<int> temp = p;
while (p.Next != null)
{
p
= p.Next;
if (temp.Data < p.Data)
{
temp
= p;
}
}
return temp.Data;
}
设一顺序表(单链表)中的元素值递增有序,将元素x插入到表中适当的位置,
//并保持顺序表(单链表)的有序性
//分析时间复杂度
static void Insert(SepLinkedList<int> la, int x)
{
Node
<int> p = la.Head;
Node
<int> q = new Node<int>();
Node
<int> temp = new Node<int>(x);
if (x < p.Data) //小于第一个元素
{
temp.Next
= la.Head;
la.Head
= temp;
}
while (p.Next != null)
{
q
= p;
p
= p.Next;
if (q.Data <= x && x <= p.Data)
{

temp.Next
= p;
q.Next
= temp;
return;
}
}
if (p != null)
{
p.Next
= temp;
}

}
/// <summary>
/// 提取单链表中不重复的数据元素
/// </summary>
/// <param name="l"></param>
/// <returns></returns>
static SepLinkedList<int> Purge(SepLinkedList<int> l)
{
SepLinkedList
<int> result = new SepLinkedList<int>();
Node
<int> p = l.Head;
Node
<int> q = new Node<int>();
Node
<int> s = new Node<int>();

//将第一个元素加入结果链表
s = p;
p
= p.Next;
s.Next
= null;
result.Head
= s;

while (p != null)
{
s
= p;
p
= p.Next;
q
= result.Head;

while (q != null && q.Data != s.Data)
{
q
= q.Next;
}
if (q == null)
{
s.Next
= result.Head;
result.Head
= s;
}
}
return result;

}
/// <summary>
/// 将两个存储整型数据元素升序排列的单链表合并,并保持升序
/// 算法思想:将la中的每个元素与lb的元素依次比较,并将每次比较中的小者加入结果链表中,最后将剩余的数据元素加入结果链表中
/// </summary>
/// <param name="la"></param>
/// <param name="lb"></param>
/// <returns></returns>
static SepLinkedList<int> Merge(SepLinkedList<int> la, SepLinkedList<int> lb)
{
Node
<int> p = la.Head;
Node
<int> q = lb.Head;
int temp = 0;
SepLinkedList
<int> result = new SepLinkedList<int>();
while (p != null && q != null)
{
if (p.Data < q.Data)
{
temp
= p.Data;
p
= p.Next;
}
else
{
temp
= q.Data;
q
= q.Next;
}

}
result.Append(temp);
if (p == null)
{
p
= q;
}
while (p != null)
{
temp
= p.Data;
result.Append(temp);
p
= p.Next;
}
return result;

}
相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
1月前
【数据结构】单链表(长期维护)(1)
【数据结构】单链表(长期维护)(1)
|
7天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
9天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
9天前
|
存储 算法 C语言
数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解
本文详细介绍了单链表的理论知识,涵盖单链表的定义、优点与缺点,并通过示例代码讲解了单链表的初始化、插入、删除、查找等核心操作。文中还具体分析了按位序插入、指定节点前后插入、按位序删除及按值查找等算法实现,并提供了尾插法和头插法建立单链表的方法,帮助读者深入理解单链表的基本原理与应用技巧。
|
9天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
9天前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。
|
1月前
|
存储 Java
数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储
这篇文章通过Java代码示例展示了如何实现哈希表,包括定义结点类、链表类、数组存储多条链表,并使用简单的散列函数处理冲突,以及如何利用哈希表存储和查询学生信息。
数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储
|
1月前
|
存储
【数据结构】单链表-->详细讲解,后赋源码
【数据结构】单链表-->详细讲解,后赋源码
21 4
|
1月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
51 7
|
30天前
|
算法 索引
【初阶数据结构篇】单链表算法题进阶
深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。