单链表的节点数,合并,相交,反转

1.求节点数

function getNodeNum(head){
    if(head == null){
        return 0;
    }
    var len = 0,
        cur = head;
    while(cur != null){
        len++;
        cur = cur.next;
    }
    return len;
}

2. 查找倒数第K个节点

//可以统计节点个数,再找到第n-(k-1)个节点,最后一个节点的倒数第1个,倒数第K个节点是n-(k-1)
//这里使用双指针法,两个指针,第一个指针先走到第k个节点,前后两个指针相差k-1,
//这样两个指针一起走,首个指针走到最后一个节点,第二个节点指向倒数第k个节点
function getLastKthNode(head,k){
    if(k == 0 || head == null){
        return null;
    }
    var ahead = head,
        behind = head;
    while(k > 1 && ahead != null){
        ahead = ahead.next;
        k--;
    }
    //说明链表长度不足k
    if(k > 1 || ahead == null){
        return null;
    }
    while(ahead.next != null){
        behind = behind.next;
        ahead = ahead.next;
    }
    return behind;
}

3.查找中间节点

//用双指针法,快慢指针,慢指针每次一步,快指针每次两步,当快指针走到尾部,慢指针走到中间节点
function getMiddleNode(head){
    if(head == null || head.next == null){
        return head;
    }
    var ahead = null,
        behind = null;
    while(ahead.next != null){
        ahead = ahead.next;
        behind = behind.next;
        if(ahead.next != null){
            ahead = ahead.next;
        }
    }
    return behind;
}

4. 合并两个有序链表为一个新的有序链表

function mergeSortedList(head1,head2){
    if(head1 == null){
        return head2;
    }
    if(head2 == null){
        return head1;
    }
    var mhead = new Node();
    var h1 = head1.next,
        h2 = head2.next;
    if(h1.val < h2.val){
        mhead.next = h1;
        mhead.next.next = null;
        h1 = h1.next;
    }
    else{
        mhead.next = h2;
        mhead.next.next = null;
        h2 = h2.next;
    }
    var temp = mhead;
    while(h1 != null && h2 != null){
        if(h1.key < h2.key){
            temp.next = h1;
            h1 = h1.next;
            temp = temp.next;
            temp.next = null;
        }
        else{
            temp.next = h2;
            h2 = h2.next;
            temp = temp.next;
            temp.next = null;
        }
    }
    if(h1 != null){
        temp.next = h1;
    }
    else{
        temp.next = h2;
    }
    return mhead;
}

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

//判断依据,两个单链表相交之后,其后面的链表是共有的,形成一个三条线共用一个顶点的形状
//因此判断两个链表的最后一个点是否相同,即可判定是否有交点
function IsIntersected(head1,head2){
    if(head1 == null || head2 == null){
        return false;
    }
    var tail1 = head1,
        tail2 = head2;
    while(tail1.next != null){
        tail1 = tail1.next;
    }
    while(tail2.next != null){
        tail2 = tail2.next;
    }
    return tail1 == tail2;
}

6.求两个链表的第一个交点

//求两个链表的第一个交点,先判断是否相交,如果不相交,返回null,否则,将长度大的链表的指针
//向前移动两个链表的长度差距离,这样两个链表指针距离交点的长度相等,两个指针同时向前移动,
//当指针相同时候,即为第一个交点
function getFirstCommonNode(head1,head2){
    if(head1 == null || head2 == null){
        return false;
    }
    var tail1 = head1,
        len1 = 0,
        tail2 = head2,
        len2 = 0;
    while(tail1.next != null){
        tail1 = tail1.next;
        len1++;
    }
    while(tail2.next != null){
        tail2 = tail2.next;
        len2++;
    }
    if(tail1 != tail2){
        return null;
    }
    var count = len1 - len2;
    count = Math.abs(count);
    tail1 = head1;
    tail2 = head2;
    if(count > 0){
        while(count--){
            tail1 = tail1.next;
        }
    }
    else{
        while(count--){
            tail2 = tail2.next;
        }
    }
    while(tail1 != tail2){
        tail1 = tail1.next;
        tail2 = tail2.next;
    }
    return tail1;
}

7.反转链表

//从尾到头打印链表,对于颠倒顺序的问题,首先想到栈,先进后出,要么使用自定义栈,
//要么使用系统栈,即递归
function reverseTraverse(head){
    var stack = [];
    var cur = head;
    while(cur != null){
        stack.push(cur);
    }
    while(stack.length > 0){
        var node = stack.pop();
        console.log(‘val ‘ + node.val)
    }
}
//使用递归(系统栈,递归栈的思想)
function reverseTraverse(head){
    //递归出口,出栈条件
    if(head == null){
        return;
    }
    else{
        reverseTraverse(head.next);
        //递归出口,即出栈时候,才会执行此句打印,所以是倒着打印
        console.log(‘val ‘ + head.val);
    }
}
//反转链表,利用头插法,将后面的节点不断插入到head节点后面
function reverse(head){
    if(head == null || head.next == null){
        return;
    }
    var cur = head.next,
        next = cur.next;
    //第二个节点与第三个节点断开,否则会形成环
    cur.next = null;
    while(next != null){
        cur = next;
        next = cur.next;
        cur.next = head.next;
        head.next = cur;
    }
}

参考:http://blog.csdn.net/luckyxiaoqiang/article/details/7393134

时间: 2024-10-06 14:12:32

单链表的节点数,合并,相交,反转的相关文章

看图理解单链表的反转

如何把一个单链表进行反转? 方法1:将单链表储存为数组,然后按照数组的索引逆序进行反转. 方法2:使用3个指针遍历单链表,逐个链接点进行反转. 方法3:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾. 方法4:   递归(相信我们都熟悉的一点是,对于树的大部分问题,基本可以考虑用递归来解决.但是我们不太熟悉的一点是,对于单链表的一些问题,也可以使用递归.可以认为单链表是一颗永远只有左(右)子树的树,因此可以考虑用递归来解决.或者说,因为单

单链表反转问题

单链表反转问题 基本问题 如何将单链表反转? 算法实现 /** * * Description: 单链表反转. * * @param head * @return ListNode */ public static ListNode reverseList(ListNode head) { if (head == null) { return head; } ListNode prev = null; ListNode current = head; ListNode next = null;

线性表总结(单链表的反转)

主要总结单链表反转的几种方法 第一种方法貌似是递归,不太懂,第二种方法使用三个指针逐一完成逆置 结构体定义:class ListNode { int val; ListNode next; ListNode(int x) { //这步没看懂,是结构体里引用了自己吗 val = x; next = null; } } 1 // 1.就地反转法 2 public ListNode reverseList1(ListNode head) { 3 if (head == null) 4 return h

1.11判断两个无环单链表是否相交

判断两个无环单链表是否交叉 题目描述: 如上图,这两个链表相交于结点5,要求判断两个链表是否相交,如果相交,找出相交处的结点. 解题思路: 方法一:Hash 法 如上图所示,如果两个链表相交,那么它们一定会有公共的结点,由于结点的地址或引用可以作为结点的唯一标识,因此,可以通过判断两个链表中的结点是否有相同的地址或引用来判断链表是否相交. 方法二:首尾相接法 将这两个链表首尾相连(例如把链表headl尾结点链接到head2的头指针),然后检测这个链表是否存在环,如果存在,则两个链表相交,而环入口

单链表 知识点学习--Android地基系列(一)

嗯,看别人整理过,自己再做的笔记,题目都是常见的必考题目,嘻嘻嘻,单链 表的基础知识我就不写了,太多人写了. 看前注意!!!!!!!涉及C知识较多,C知识我以后再考虑是否写一篇附加文 可以辅助以后的Android必备地基系列博文 struct ListNode { int data; ListNode * Next; }; 1.求链表中结点个数 思路:若链表为空,返回0:循环判断链表下一个指针是否为空,no,长度++(初始化用unsigned int  length = 0),直到下一个为nul

单链表操作实例程序

#include <iostream> #include <iomanip> using namespace std; typedef struct node { int val; node *next; }node; node * create_list(); void traverse_list(node *pHead); int get_len_list(node *pHead); bool delete_list(node *pHead,int pos,int &v

单链表的相关操作

#ifndef _SLIST_H #define _SLIST_H #ifdef __cplusplus extern "C" { #endif /*******1. 不带头结点的单链表*****/ /***** *@链表结点结构定义 *@ m_data:数据 *@m_pNext:指向下一结点的指针 ***/ struct listNode { int m_data; listNode* m_pNext; }; /******* *@ 用数组array初始化链表,数组元素个数为n *@

数据结构与算法系列(1)-单链表类的实现(C++)

通过定义一个C++类封装单链表这种数据结构, 封装的方法有: 1.通过输入创建单链表: 2.获取单链表的数据元素个数: 3.打印输出单链表中各个元素: 4.搜索某个元素在单链表中的位置: 5.在某个位置之后插入一个结点: 6.在某个位置删除一个节点: 7.单链表逆置: 8.单链表是否存在回环的判定: 9.单链表的升序排序: 10.两个单链表的升序合并: 11.两个单链表的降序合并. 注:单链表的排序采用的是快速排序的方法. 下面是C++写的程序代码,附运行截图. #include <iostre

线性表之单链表学习小结(初学数据结构必看)

花了好几个小时,详细规划出了整个过程,包括所有基本操作...有什么疑问请下方留言 #include<iostream> using namespace std; #define ElemType char #define ERROR 0 #define OK 1 typedef struct Node { ElemType data; struct Node *next; }Node,*LinkList; void init_linklist(LinkList L)/*对单链表进行初始化*/