# 算法大全（1）单链表

1.单链表反转

2.找出单链表的倒数第4个元素

3.找出单链表的中间元素

4.删除无头单链表的一个节点

5.两个不交叉的有序链表的合并

6.有个二级单链表，其中每个元素都含有一个指向一个单链表的指针。写程序把这个二级链表称一级单链表。

7.单链表交换任意两个元素（不包括表头）

8.判断单链表是否有环？如何找到环的“起始”点？如何知道环的长度？

9.判断两个单链表是否相交

10.两个单链表相交，计算相交点

11.用链表模拟大整数加法运算

12.单链表排序

13.删除单链表中重复的元素

public class Link
{
public string Data;
{
this.Next = next;
this.Data = data;
}
}



static void Main(string[] args)
{

    Link curr = head;
    while (curr != null)
{
Console.WriteLine(curr.Data);
curr = curr.Next;
}
}

1.单链表反转

public static Link ReverseLink1(Link head)
{
//if no elements or only one element exists
if (curr == null || curr.Next == null)
{
}
//if more than one element
while (curr.Next != null)
{
next = curr.Next;       //1
nextnext = next.Next;   //2
curr.Next = nextnext;   //5
}
}

public static void ReverseLink2(Link head)
{
{
}
}


public static Link ReverseLink3(Link head)
{
//if no elements or only one element exists
}

我们观测到：
head.Next = ReverseLink(head.Next);
这句话的意思是为ReverseLink方法生成的逆序链表添加一个空表头。
接下来就是递归的核心算法ReverseLink了：
static Link ReverseLink(Link head)
{
}

head.Next.Next = head;  //1


2.找出单链表的倒数第4个元素

static Link GetLast4thOne(Link head)
{
for (int i = 0; i < 4; i++)
{
if (first.Next == null)
throw new Exception("Less than 4 elements");
first = first.Next;
}
while (first != null)
{
first = first.Next;
second = second.Next;
}
return second;
}

static Link GetLast4thOneByArray(Link head)
{
int i = 0;
while (curr.Next != null)
{
arr[i] = curr.Next;
curr = curr.Next;
i = (i + 1) % 4;
}
if (arr[i] == null)
throw new Exception("Less than 4 elements");
return arr[i];
}

3.找出单链表的中间元素

static Link GetMiddleOne(Link head)
{
while (first != null && first.Next != null)
{
first = first.Next.Next;
second = second.Next;
}
return second;
}

static void Main(string[] args)
{
bool isOdd = true;
if (isOdd)
{
Console.WriteLine(middle.Data);
}
else
{
Console.WriteLine(middle.Data);
Console.WriteLine(middle.Next.Data);
}
}
{
while (first != null && first.Next != null)
{
first = first.Next.Next;
second = second.Next;
}
if (first != null)
isOdd = false;
return second;
}

4.一个单链表，很长，遍历一遍很慢，我们仅知道一个指向某节点的指针curr，而我们又想删除这个节点。

curr.Data = curr.Next.Data;
curr.Next = curr.Next.Next;

5.两个不交叉的有序链表的合并

static Link MergeTwoLink(Link head1, Link head2)
{
//compare until one link run to the end
while (curr1.Next != null && curr2.Next != null)
{
if (curr1.Next.Data < curr2.Next.Data)
{
curr1 = curr1.Next;
}
else
{
curr2 = curr2.Next;
}
pre.Next = curr;
pre = pre.Next;
}
//if head1 run to the end
while (curr1.Next != null)
{
curr1 = curr1.Next;
pre.Next = curr;
pre = pre.Next;
}
//if head2 run to the end
while (curr2.Next != null)
{
curr2 = curr2.Next;
pre.Next = curr;
pre = pre.Next;
}
}

static Link MergeTwoLink2(Link head1, Link head2)
{
//compare until one link run to the intersect
while (curr1.Next != intersect && curr2.Next != intersect)
{
if (curr1.Next.Data < curr2.Next.Data)
{
curr1 = curr1.Next;
}
else
{
curr2 = curr2.Next;
}
pre.Next = curr;
pre = pre.Next;
}
//if head1 run to the intersect
if (curr1.Next == intersect)
{
while (curr2.Next != null)
{
curr2 = curr2.Next;
pre.Next = curr;
pre = pre.Next;
}
}
//if head2 run to the intersect
else if (curr2.Next == intersect)
{
while (curr1.Next != null)
{
curr1 = curr1.Next;
pre.Next = curr;
pre = pre.Next;
}
}
}

6.有个二级单链表，其中每个元素都含有一个指向一个单链表的指针。写程序把这个二级链表展开称一级单链表。

public class Link
{
public int Data;
{
this.Next = next;
this.Data = data;
}
}
{
{
this.Next = next;
}
}

public static CascadeLink GenerateCascadeLink()
{
}
就是说，这些单链表的表头head1、head2、head3、head4……，它们组成了一个二级单链表head：null –> head1 –> head2 –> head3 –> head4  –>

public static Link GenerateNewLink(CascadeLink head)
{
while (curr1 != null)
{
curr2.Next = curr1.Next.Next;
while (curr2.Next != null)
{
curr2 = curr2.Next;
}
}
}

其中，curr2.Next = curr1.Next.Next; 这句话是关键，它负责把上一个单链表的表尾和下一个单链表的非空表头连接起来。

7.单链表交换任意两个元素（不包括表头）

public static Link SwitchPoints(Link head, Link p, Link q)
{
throw new Exception("No exchange with head");
if (p == q)
//find p and q in the link

int count = 0;

while (curr != null)
{
if (curr.Next == p)
{
pre1 = curr;
count++;
if (count == 2)
break;
}
else if (curr.Next == q)
{
pre2 = curr;
count++;
if (count == 2)
break;
}
curr = curr.Next;
}
curr = curr1.Next;
pre1.Next = curr2;
curr1.Next = curr2.Next;
pre2.Next = curr1;
curr2.Next = curr;
}
注意特例，如果相同元素，就没有必要交换；如果有一个是表头，就不交换。

8.判断单链表是否有环？如何找到环的“起始”点？如何知道环的长度？

static bool JudgeCircleExists(Link head)
{
while (second.Next != null && second.Next.Next != null)
{
second = second.Next.Next;
first = first.Next;
if (second == first)
return true;
}
return false;
}

static int GetCircleLength(Link point)
{
int length = 1;
while (curr.Next != point)
{
length++;
curr = curr.Next;
}
return length;
}

static int GetLengthFromHeadToPoint(Link head, Link point)
{
int length = 1;
while (curr != point)
{
length++;
curr = curr.Next;
}
return length;
}


private static Link FindIntersect(Link head)
{
//get the point in the circle
bool result = JudgeCircleExists(head, ref p);
if (!result) return null;
int M = 1;
while (curr1 != p)
{
M++;
curr1 = curr1.Next;
}
//circle length
int N = 1;
while (curr2 != p)
{
N++;
curr2 = curr2.Next;
}
//recover curr1 & curr2
curr2 = p.Next;
//make 2 links have the same distance to the intersect
if (M > N)
{
for (int i = 0; i < M - N; i++)
curr1 = curr1.Next;
}
else if (M < N)
{
for (int i = 0; i < N - M; i++)
curr2 = curr2.Next;
}
//goto the intersect
while (curr1 != p)
{
if (curr1 == curr2)
{
return curr1;
}
curr1 = curr1.Next;
curr2 = curr2.Next;
}
return null;
}

9.判断两个单链表是否相交

static bool JudgeIntersectLink1(Link head1, Link head2)
{
Hashtable ht = new Hashtable();
//store all the elements of link1
while (curr1.Next != null)
{
ht[curr1.Next] = string.Empty;
curr1 = curr1.Next;
}
//check all the elements in link2 if exists in Hashtable or not
while (curr2.Next != null)
{
//if exists
if (ht[curr2.Next] != null)
{
return true;
}
curr2 = curr2.Next;
}
return false;
}


static bool JudgeIntersectLink2(Link head1, Link head2)
{
bool exists = false;

//goto the end of the link1
while (curr1.Next != null)
{
curr1 = curr1.Next;
}
while (curr2.Next != null)
{
{
exists = true;
break;
}
curr2 = curr2.Next;
}
//recover original status, whether exists or not
curr1.Next = null;
return exists;
}


static bool JudgeIntersectLink3(Link head1, Link head2)
{
//goto the end of the link1
while (curr1.Next != null)
{
curr1 = curr1.Next;
}
//goto the end of the link2
while (curr2.Next != null)
{
curr2 = curr2.Next;
}
if (curr1 != curr2)
return false;
else
return true;
}

10.两个单链表相交，计算相交点

public static Link GetIntersect(Link head1, Link head2)
{
int M = 0, N = 0;
//goto the end of the link1
while (curr1.Next != null)
{
curr1 = curr1.Next;
M++;
}
//goto the end of the link2
while (curr2.Next != null)
{
curr2 = curr2.Next;
N++;
}
if (M > N)
{
for (int i = 0; i < M - N; i++)
curr1 = curr1.Next;
}
else if (M < N)
{
for (int i = 0; i < N - M; i++)
curr2 = curr2.Next;
}
while (curr1.Next != null)
{
if (curr1 == curr2)
{
return curr1;
}
curr1 = curr1.Next;
curr2 = curr2.Next;
}
return null;
}

11.用链表模拟大整数加法运算

//head1 length > head2, so M > N
{
// goto the end
return 0;
int temp = 0;
int result = 0;
if (M > N)
{
return temp >= 10 ? 1 : 0;
}
else // M == N
{
return temp >= 10 ? 1 : 0;
}
}

12.单链表排序

static int[] InsertSort(int[] arr)
{

for (int i = 1; i < arr.Length; i++)
{

for (int j = i; (j > 0&& arr[j] < arr[j - 1]; j--)
{
arr[j]
= arr[j] ^ arr[j - 1];
arr[j
- 1= arr[j] ^ arr[j - 1];
arr[j]
= arr[j] ^ arr[j - 1];
}
}

return arr;
}

public static Link SortLink(Link head)
{
{
if (curr1.Next == null)
break;
min = curr1;
for (Link curr2 = curr1.Next; curr2 != null; curr2 = curr2.Next)
{
//swap curr1 and curr2
if (curr2.Data < curr1.Data)
{
min = curr2;
curr2 = curr1;
curr1 = min;
pre1.Next = curr1;
curr2.Next = curr1.Next;
curr1.Next = pre2;
//if exchange element n-1 and n, no need to add reference from pre2 to curr2, because they are the same one
if (pre2 != curr2)
pre2.Next = curr2;
}
pre2 = curr2;
}
pre1 = min;
pre2 = min.Next;
}
}

13.删除单链表中重复的元素

public static Link DeleteDuplexElements(Link head)
{
Hashtable ht = new Hashtable();
while (curr != null)
{
if (curr.Next == null)
{
break;
}
if (ht[curr.Next.Data] != null)
{
curr.Next = curr.Next.Next;
}
else
{
ht[curr.Next.Data] = "";
}
curr = curr.Next;
}
}

posted @ 2009-12-11 00:09  包建强  Views(21724)  Comments(51Edit  收藏  举报