`

算法大全(1)单链表 2

阅读更多

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

分别遍历两个单链表,计算出它们的长度M和N,假设M比N大,则长度M的链表先前进M-N,然后两个链表同时以步长1前进,前进的同时比较当前的元素,如果相同,则必是交点。

public static Link GetIntersect(Link head1, Link head2)
{
    Link curr1 = head1;
    Link curr2 = 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++;
    }
    //return to the begining of the link
    curr1 = head1;
    curr2 = head2;
    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.用链表模拟大整数加法运算

例如:9>9>9>NULL + 1>NULL =>  1>0>0>0>NULL

肯定是使用递归啦,不然没办法解决进位+1问题,因为这时候要让前面的节点加1,而我们的单链表是永远指向前的。

此外对于999+1=1000,新得到的值的位数(4位)比原来的两个值(1个1位,1个3位)都多,所以我们将表头的值设置为0,如果多出一位来,就暂时存放到表头。递归结束后,如果表头为1,就在新的链表外再加一个新的表头。

//head1 length > head2, so M > N
public static int Add(Link head1, Link head2, ref Link newHead, int M, int N)
{
    // goto the end
    if (head1 == null)
        return 0;
    int temp = 0;
    int result = 0;
    newHead = new Link(null, 0);
    if (M > N)
    {
        result = Add(head1.Next, head2, ref newHead.Next, M - 1, N);
        temp = head1.Data + result;
        newHead.Data = temp % 10;
        return temp >= 10 ? 1 : 0;
    }
    else // M == N
    {
        result = Add(head1.Next, head2.Next, ref newHead.Next, M - 1, N - 1);
        temp = head1.Data + head2.Data + +result;
        newHead.Data = temp % 10;
        return temp >= 10 ? 1 : 0;
    }
}

这里假设head1比head2长,而且M、N分别是head1和head2的长度。

 

12.单链表排序

无外乎是冒泡、选择、插入等排序方法。关键是交换算法,需要额外考虑。第7题我编写了一个交换算法,在本题的排序过程中,我们可以在外层和内层循环里面,捕捉到pre1和pre2,然后进行交换,而无需每次交换又要遍历一次单链表。

在实践中,我发现冒泡排序和选择排序都要求内层循环从链表的末尾向前走,这明显是不合时宜的。

所以我最终选择了插入排序算法,如下所示:

先给出基于数组的算法: 

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

  

仿照上面的思想,我们来编写基于Link的算法:

public static Link SortLink(Link head)
{
    Link pre1 = head;
    Link pre2 = head.Next;
    Link min = null;
    for (Link curr1 = head.Next; curr1 != null; curr1 = min.Next)
    {
        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;
    }
    return head;
}

 

值得注意的是,很多人的算法不能交换相邻两个元素,这是因为pre2和curr2是相等的,如果此时还执行pre2.Next = curr2; 会造成一个自己引用自己的环。

 

交换指针很是麻烦,而且效率也不高,需要经常排序的东西最好不要用链表来实现,还是数组好一些。

 

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

用Hashtable辅助,遍历一遍单链表就能搞定。

实践中发现,curr从表头开始,每次判断下一个元素curr.Netx是否重复,如果重复直接使用curr.Next = curr.Next.Next; 就可以删除重复元素——这是最好的算法。唯一的例外就是表尾,所以到达表尾,就break跳出while循环。

public static Link DeleteDuplexElements(Link head)
{
    Hashtable ht = new Hashtable();
    Link curr = head;
    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;
    }
    return head;
}

 

 

结语:

单链表只有一个向前指针Next,所以要使用1-2个额外变量来存储当前元素的前一个或后一个指针。

尽量用while循环而不要用for循环,来进行遍历。

哇塞,我就是不用指针,照样能“修改地址”,达到和C++同样的效果,虽然很烦~

遍历的时候,不要在while循环中head=head.Next;这样会改变原先的数据结构。我们要这么写:Link curr=head;然后curr=curr.Next;

有时我们需要临时把环切开,有时我们需要临时把单链表首尾相连成一个环。

究竟是玩curr还是curr.Next,根据不同题目而各有用武之地,没有定论,不必强求。

分享到:
评论

相关推荐

    单链表操作算法合集

    代码中包含单链表的常用操作,主要实现以下六个算法: 1.单链表的就地反转 2.链表相交或求公共起始节点 3.求链表倒数第n个节点 4.删除单个节点 5.判断链表是否有环 6.将2个递增的链表合并为递减链表 并全部调试通过...

    单链表操作算法举例,单链表操作算法举例

    ### 单链表操作算法详解 #### 一、引言 在计算机科学中,链表是一种常见的线性数据结构,其元素并非存储在连续的内存空间内,而是通过每个节点内的指针链接起来。单链表是链表的一种基本形式,每个节点仅包含一个...

    Java算法实例-单链表操作

    在这个"Java算法实例-单链表操作"中,我们将探讨如何在Java中实现单链表,包括其基本操作如插入、删除、遍历等。这些操作对于理解和解决各种算法问题至关重要,尤其对于学习和准备编程考试的学员来说,是非常实用的...

    单链表上的简单选择排序算法

    当我们需要在单链表这种非数组结构上进行排序时,需要对基本的简单选择排序算法进行一些调整。接下来,我们将详细探讨如何在单链表上实现简单选择排序。 **一、单链表基础知识** 单链表是一种线性数据结构,由一...

    实现循环单链表的各种基本运算的算法

    数据结构与算法 李春葆 第五版实验报告2.22 含代码和结果

    数据结构和算法应用分解单链表.cpp

    数据结构和算法应用分解单链表.cpp

    算法各大公司的笔试题目算法部分之单链表的各种逆置排序.txt

    ### 单链表逆置与排序算法解析 #### 引言 在计算机科学领域中,数据结构和算法一直是核心主题之一。单链表作为一种基本的数据结构,在实际应用中有着广泛的应用场景,尤其是在软件开发和系统设计中。对于求职者而言...

    删除单链表中值相同的多余结点的算法

    根据给定文件的信息,本文将详细探讨一种用于删除单链表中值相同的多余节点的算法。此算法采用C++语言实现,并通过具体的代码示例来解释其工作原理。 ### 删除单链表中值相同的多余节点的算法 在数据结构的学习...

    对单链表实现就地逆置算法

    对以单链表为存储结构的表实现就地逆置,即在原有空间上实现逆置,不开辟新空间

    【数据结构作业二】写出单链表结点的结构体类型定义及查找、插入、删除算法,并以单链表作存储结。。。 定义线性表节点的结构.pdf

    下面是单链表的结构体类型定义、查找、插入、删除算法实现及应用实例。 一、单链表结构体类型定义 单链表的结构体类型定义可以使用C++语言实现,如下所示: ```cpp typedef int elementType; typedef struct lnode...

    写一个算法将一单链表逆置。要求操作在原链表上进行。

    写一个算法将一单链表逆置。要求操作在原链表上进行。

    单链表二叉树算法大全

    这份"单链表二叉树算法大全"压缩包包含了这两个主题的详细算法集合,是准备笔试和面试的宝贵资源。 **单链表** 单链表是一种线性数据结构,每个元素(节点)包含两部分:数据域存储实际信息,以及指针域指向下一个...

    单链表的快速排序算法

    单链表是一种基础的数据结构,它由一系列节点构成,每个节点包含数据元素和指向下一个节点的指针。...通过阅读和理解这份文档,你可以深入学习如何将快速排序算法应用于单链表,并进一步提升你的编程技巧。

    Java算法篇-单链表反转详解.pptx.pptx

    作为一种基础且重要的数据结构,单链表的掌握对于学习算法和提升编程能力具有极其关键的作用。本文将深入探讨单链表的定义、特性、应用以及反转算法的实现,帮助读者全面理解并掌握这一重要的数据结构。 首先,我们...

    顺序表与单链表基本运算算法.doc

    顺序表与单链表基本运算算法 顺序表是一种基本的数据结构,它是由一组连续的存储单元组成的,每个存储单元都可以存储一个数据元素。顺序表的基本运算包括创建顺序表、打印顺序表、查找顺序表中的元素、插入元素到...

    单链表逆置算法详解

    ### 单链表逆置算法详解 #### 一、引言 在计算机科学中,链表是一种常用的数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。单链表是最简单的一种链表形式,其中每个节点只包含一个指向其...

    C语言数据结构 单链表的删除算法

    单链表作为数据结构的基础部分,对于理解和实现各种算法至关重要。本话题将深入探讨如何在C语言中使用单链表,并实现一个特定的删除算法。 首先,单链表是一种线性数据结构,其中每个元素(节点)包含两个部分:...

    c语言数据结构单链表的算法

    本节将深入探讨单链表的算法,包括其定义、基本操作以及在实际问题中的应用。 单链表是由一系列节点组成的数据结构,每个节点包含两部分:数据域和指针域。数据域用于存储实际的数据,而指针域则保存下一个节点的...

    直观图形界面演示数据结构基础算法集合【单链表部分】

    1. **单链表结点的插入**: 插入操作是在已存在的链表中添加新节点。插入可能发生在链表的开头(头插法)或结尾(尾插法)。头插法时,新节点会成为新的头节点,而原头节点成为新节点的下一个节点;尾插法时,需要...

    单链表可找出最小值点

    本文将介绍如何建立一个由正整数组成的无序单链表,并编写算法实现以下功能:找出最小值结点,且显示该数值;若该数值为奇数,则将其与直接后继结点的数值交换。若为偶数,则将其直接后继结点删除。 首先,我们需要...

Global site tag (gtag.js) - Google Analytics