您的位置:首页 > 编程语言 > C#

c#实现单链表的操作

2008-11-06 07:52 260 查看
以下是用c#实现的单链表的基本操作,调试环境为vs2008。(注:对于链表有带头结点和不带头结点的两种,其中部分方法给出了带头结点和不带头结点两种算法)

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

#region 测试带头结点的链表的建立及转置

//Program p = new Program();

//LinkList<int> ll = p.H_CreateListHead();

//Console.WriteLine("生成的单链表如下:");

//for (int i = 1; i <= ll.GetLength(); i++)

//{

// Console.WriteLine(" {0}", ll.GetElem(i));

//}

////转置后的单链表

//Console.WriteLine("转置后的单链表如下:");

//ll.H_Reverse();

//for (int i = 1; i <= ll.GetLength(); i++)

//{

// Console.WriteLine(" {0}", ll.GetElem(i));

//}

//Console.ReadLine();

#endregion

#region 测试不带头结点的链表的建立及转置

//Program p = new Program();

//LinkList<int> ll = p.N_CreateListHead();

//Console.WriteLine("生成的单链表如下:");

//for (int i = 1; i <= ll.GetLength(); i++)

//{

// Console.WriteLine(" {0}", ll.GetElem(i));

//}

////转置后的单链表

//Console.WriteLine("转置后的单链表如下:");

//ll.N_Reverse();

//for (int i = 1; i <= ll.GetLength(); i++)

//{

// Console.WriteLine(" {0}", ll.GetElem(i));

//}

//Console.ReadLine();

#endregion

#region 将两个按升序排列的单链表合并成一个新的有序单链表

////***********************************************************************

////对应于用头插法建立的单链表,插入的的数据和用户输入的顺序正好相反,

////所以进行合并前,必须先将两个单链表进行转置,

////才能正确的输出合并后的有序表,进行头插法合并输出的就是新的有序链表,

////进行尾插法合的到的是逆序的有序链表,并且时间复杂度由头插法的O((m+n)*k),

////变成尾插法的0(m+n),m为Ha的表长,n为Hb的表长,k为Hc的表长

////************************************************************************

//Program p = new Program();

//Console.WriteLine("请输入第一个有序链表");

//LinkList<int> linklist1 = p.H_CreateListHead();

//Console.WriteLine("请输入第二个有序链表");

//LinkList<int> linklist2 = p.H_CreateListHead();

//Console.WriteLine("用头插法生成第一个单链表:");

//for (int i = 1; i <= linklist1.GetLength(); i++)

//{

// Console.Write(" {0}", linklist1.GetElem(i));

//}

//Console.WriteLine();

//Console.WriteLine("用头插法生成第一个单链表转置后的有序链表:");

//linklist1.H_Reverse();

//for (int i = 1; i <= linklist1.GetLength(); i++)

//{

// Console.Write(" {0}", linklist1.GetElem(i));

//}

//Console.WriteLine();

//Console.WriteLine("用头插法生成第二个单链表:");

//for (int i = 1; i <= linklist2.GetLength(); i++)

//{

// Console.Write(" {0}", linklist2.GetElem(i));

//}

//Console.WriteLine();

//Console.WriteLine("用头插法生成第二个单链表转置后的有序链表:");

//linklist2.H_Reverse();

//for (int i = 1; i <= linklist2.GetLength(); i++)

//{

// Console.Write(" {0}", linklist2.GetElem(i));

//}

//Console.WriteLine();

////合并后的单链表

//Console.WriteLine("合并后的有序单链表如下:");

//LinkList<int> linklist3 = p.Merge2(linklist1, linklist2);

//for (int i = 1; i <= linklist3.GetLength(); i++)

//{

// Console.Write(" {0}", linklist3.GetElem(i));

//}

//Console.ReadLine();

#endregion

#region 输出一个链表中所有不重复的节点

Program p = new Program();

Console.WriteLine("请输入个有序链表");

LinkList<int> linklist1 = p.H_CreateListHead();

Console.WriteLine("用头插法生成的单链表:");

for (int i = 1; i <= linklist1.GetLength(); i++)

{

Console.Write(" {0}", linklist1.GetElem(i));

}

Console.WriteLine();

Console.WriteLine("去掉重复节点后的单链表:");

LinkList<int> linklist2 = p.Purge(linklist1);

for (int i = 1; i <= linklist2.GetLength(); i++)

{

Console.Write(" {0}", linklist2.GetElem(i));

}

Console.ReadLine();

#endregion

}

/// <summary>

/// 链表节点类的定义

/// </summary>

/// <typeparam name="T"></typeparam>

public class Node<T>

{

private T data;

private Node<T> next;

//构造器

public Node(T val, Node<T> p)

{

data = val;

next = p;

}

//构造器

public Node(T val)

{

data = val;

next = null;

}

//构造器

public Node(Node<T> p)

{

next = p;

}

//构造器

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; }

}

}

/// <summary>

/// 链表类的定义(添加对链表头的应用)

/// </summary>

/// <typeparam name="T"></typeparam>

private class LinkList<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("链表为空或者位置不正确!");

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;

}

}

public T Delete(int i)

{

if (IsEmpty() || i < 0)

{

Console.WriteLine("链表为空或者位置不正确");

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)

{

q = p;

p = p.Next;

j++;

}

if (j == i)

{

q.Next = p.Next;

return p.Data;

}

else

{

Console.WriteLine("该节点没有找到!");

return default(T);

}

}

//获取单链表的第i个元素

public T GetElem(int i)

{

if (IsEmpty() || i < 1)

{

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);

}

}

//在单链表中查找值为value的节点

public int Locate(T value)

{

if (IsEmpty())

{

Console.WriteLine("链表为空!");

return -1;

}

Node<T> p = new Node<T>();

p = head;

int j = 1;

while (!p.Data.Equals(value) && p.Next != null)

{

p = p.Next;

j++;

}

if (j <= GetLength())

{

return j;

}

else

{

Console.WriteLine("没有找到匹配的数据!");

return -1;

}

}

//实现带头结点单链表的转置

public void H_Reverse()

{

Node<T> p = head.Next;

Node<T> q = new Node<T>();

head.Next = null;

while (p != null)

{

q = p;

p = p.Next;

q.Next = head.Next;

head.Next = q;

}

}

//实现不带头结点的单链表转置(不带头结点的方法是构造一个虚拟头结点,最后将head指向第一个节点)

public void N_Reverse()

{

Node<T> p = head;

Node<T> q = new Node<T>();

Node<T> r = new Node<T>();

while (p != null)

{

q = p;

p = p.Next;

q.Next = r.Next;

r.Next = q;

}

head = q;

}

}

/// <summary>

/// 在头部插入节点建立不带头结点的单链表

/// </summary>

/// <returns></returns>

private LinkList<int> N_CreateListHead()

{

int d;

LinkList<int> L = new LinkList<int>();

d = int.Parse(Console.ReadLine());

while (d != -1)

{

Node<int> p = new Node<int>(d);

p.Next = L.Head;

L.Head = p;

try

{

d = int.Parse(Console.ReadLine());

}

catch (Exception e)

{

d = 0;

}

}

return L;

}

/// <summary>

/// 在头部插入节点建立带头结点的单链表

/// </summary>

/// <returns></returns>

private LinkList<int> H_CreateListHead()

{

int d;

LinkList<int> L = new LinkList<int>();

d = int.Parse(Console.ReadLine());

while (d != -1)

{

Node<int> p = new Node<int>(d);

p.Next = L.Head;

L.Head = p;

try

{

d = int.Parse(Console.ReadLine());

}

catch (Exception e)

{

d = 0;

}

}

Node<int> q = new Node<int>();

q.Next = L.Head;

L.Head = q;

return L;

}

/// <summary>

/// 在尾部插入节点建立单链表

/// </summary>

/// <returns></returns>

private LinkList<int> CreateListTail()

{

Node<int> R = new Node<int>();

int d;

LinkList<int> L = new LinkList<int>();

R = L.Head;

try

{

d = int.Parse(Console.ReadLine());

}

catch (Exception e)

{

d = 0;

}

//输入-1结束

while (d != -1)

{

Node<int> p = new Node<int>();

if (L.Head == null)

{

L.Head = p;

}

else

{

R.Next = p;

}

R = p;

d = int.Parse(Console.ReadLine());

}

if (R != null)

{

R.Next = null;

}

return L;

}

/// <summary>

/// 将两个有序单链表合并成一个新的有序单链表(带头结点,采用尾插法)

/// </summary>

/// <param name="Ha">有序表a</param>

/// <param name="Hb">有序表b</param>

/// <returns></returns>

private LinkList<int> Merge1(LinkList<int> Ha, LinkList<int> Hb)

{

LinkList<int> Hc = new LinkList<int>();

Node<int> p = Ha.Head.Next;

Node<int> q = Hb.Head.Next;

Node<int> s = new Node<int>();

Hc = Ha;

Hc.Head.Next = null;

while (p != null && q != null)

{

if (p.Data < q.Data)

{

s = p;

p = p.Next;

}

else

{

s = q;

q = q.Next;

}

Hc.Append(s.Data);

}

if (p == null)

{

p = q;

}

while (p != null)

{

s = p;

p = p.Next;

Hc.Append(s.Data);

}

return Hc;

}

/// <summary>

/// 将两个有序单链表合并成一个新的有序单链表(带头结点,采用头插法)

/// </summary>

/// <param name="Ha">有序表a</param>

/// <param name="Hb">有序表b</param>

/// <returns></returns>

private LinkList<int> Merge2(LinkList<int> Ha, LinkList<int> Hb)

{

LinkList<int> Hc = new LinkList<int>();

Node<int> p = Ha.Head.Next;

Node<int> q = Hb.Head.Next;

Node<int> s = new Node<int>();

Hc = Ha;

Hc.Head.Next = null;

while (p != null && q != null)

{

if (p.Data < q.Data)

{

s = p;

p = p.Next;

}

else

{

s = q;

q = q.Next;

}

s.Next = Hc.Head.Next;

Hc.Head.Next = s;

}

if (p == null)

{

p = q;

}

while (p != null)

{

s = p;

p = p.Next;

s.Next = Hc.Head.Next;

Hc.Head.Next = s;

}

return Hc;

}

/// <summary>

/// 返回单链表中所有值不相同的节点

/// </summary>

/// <param name="Ha">带有相同节点值的链表</param>

/// <returns></returns>

private LinkList<int> Purge(LinkList<int> Ha)

{

LinkList<int> Hb = new LinkList<int>();

Node<int> p = Ha.Head.Next;

Node<int> q = new Node<int>();

Node<int> s = new Node<int>();

//构造一个指向Ha的新链表,如没有这句会造成Hb.Head.Next引用为空

Hb = Ha;

s = p;

p = p.Next;

s.Next = null;

Hb.Head.Next = s;

while (p != null)

{

s = p;

p = p.Next;

//令q节点每次循环都指向Hb的头结点后的那个节点

q = Hb.Head.Next;

//拿当前节点和Hb中的所有节点依次比较(q始终指向头结点后的第一个节点)

while (q != null && q.Data != s.Data)

{

q = q.Next;

}

if (q == null)

{

s.Next = Hb.Head.Next;

Hb.Head.Next = s;

}

}

return Hb;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: