`

单向链表相关

 
阅读更多

单向链表是微软笔试常考的,参考这里:http://www.cnblogs.com/tdyizhen1314/archive/2012/04/03/2431124.html

 

#include<iostream>
using namespace std;

struct node{
       int data;
       struct node* next;
};
//定义一个名字呢 

node* create(unsigned int n){
       if(n==0){
          cout<<"ensure n>0. (create failure)"<<endl;
          return NULL;
       }
       //assert(n>0);
       
       node* head=new node;//new一个struct 
       cout<<"#1:";
       cin>>head->data;
       head->next=NULL;
       
       int i;
       node *pre=head;
       node *cur=NULL;
       for(i=1;i<n;i++){
           cur=new node;
           cout<<"#"<<i+1<<":";
           cin>>cur->data;
           cur->next=NULL;
           
           pre->next=cur;
           pre=cur;
       }
       return head;
}

/*
丑方法:
node* reverse(node* list){
     node* one=list;
     node* two=NULL;
     node* three=NULL;
     
     if(list->next!=NULL)
         two=list->next;
     else
         return list;

     if(list->next->next!=NULL)
         three=list->next->next;
         
     one->next=NULL;
         
     while(two!=NULL){
         two->next=one;
         
         one=two;
         two=three;
         if(three!=NULL)
             three=three->next;
         else
             break;
     }
     
     return one;
}
*/

/*问题1:链表反转
                 思路:head指针不断后移,指针反向即可
*/
void reverse(node*& head){
     /*1. 先讨论空链表和只有一个节点的情况*/
     if(head==NULL)
         return;
     if(head->next==NULL)
         return;
     /*2. 在处理普通情况*/
     node* p=head;     
     node* q=head->next;
     
     while(q!=NULL){
         node* temp=q->next;
         q->next=p;
         
         p=q;
         q=temp;
     } 
     
     head->next=NULL;        //反转前的链表头特殊处理 
     
     head=p;
}

/*问题2:删除不知头结点链表的某个节点
如果单向链表不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点
                 思路:下一个节点的值复制给该节点,然后删除下一个节点即可 
*/
void deleteNodeInList(node*& n){
     if(n==NULL)
         return;
         
     if(n->next==NULL){
         delete n;
         n=NULL;
         return;
     }
     
     /*一般情况:存在下一个节点*/
     node* nextNode=n->next;
     
     n->data=nextNode->data;
     n->next=nextNode->next;
     
     delete nextNode;
} 

/*
  问题3:判断链表中是否有环
  思路:
        设置两个指针,一个步长为1,另一个步长为2,依次后移,如果相遇且都不为空,则有环。
  解释: 
que:
跑步能追上确实很容易理解。但问题是,跑步是连续的,而这里不是。因为有一个指针是跳两步的,不是连续的,怎么证明这样也肯定能碰上;好像只能证明一定能超过啊
ans:
画上一个圈就知道啦!速度快的开始肯定会超过慢的.
一个步长1(乌龟),另外一个步长2(兔子),因此兔子一次追上1个单位,如果确实是个圈的话肯定会追上并且是相遇在同一个单位之内! 
*/
node* hasLoop(node* head){    //返回第一次交汇的点(能写成输入参数吗)                                                                           
     if(head==NULL)
        return NULL;
     if(head->next==NULL)
        return NULL;
     
     /*至少有2个节点的单链表*/
     node* p=head;
     node* q=head;
     while(true){
         if(p==NULL || q==NULL)
             return NULL;
         if(p->next==NULL || q->next==NULL)
             return NULL;
         if(q->next->next==NULL)
             return NULL;
         
         //p步长为1后移    
         p=p->next;
         //q步长为2后移 
         q=q->next->next;
         
         //如果p,q重合在非NULL节点,则有环
         if(p==q && p!=NULL){
             return p;
         }
     }
}

/*
  问题4:找出环的入口节点 
  思路:
        当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。
假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:
2s = s + nr   <==>  s= nr
设入口环与相遇点距离为x,x<r,起点到环入口点的距离为a.
a = s - x = (n-1)r+ (r-x), 而r-x即为fast再次到环入口点时的步数
由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。         
*/
node* getLoopHead(node* list){
     node* inter;  //第一次交汇点 
     if( (inter=hasLoop(list)) !=NULL ){
         node* p=list;
         while(true){
             if(p==inter)
                 return p;
             p=p->next;
             inter=inter->next;
         }
     }
     return NULL;
}

/*
  问题5:找出倒数第k个节点 
*/
node* findLastK(node* head, unsigned int k){
      /*
        back指向开始处, front指向前于它(k-1)个位置处 
      */
      node* back=head;
      node* front=head;
      for(int i=1;i<k;i++){
          if(front==NULL)
              return NULL;
          front=front->next;
      }
      if(front==NULL)
          return NULL;
          
      /*
        后移 
      */
      while(front->next){
          back=back->next;
          front=front->next;
      }
      return back;
}

/*
  问题6: 《编程之美》 3.6 判断两个链表是否相交 
*/
void traverse(node* list){
	node* p=list;
	while(p!=NULL){
		cout<<p->data<<"\t";
		p=p->next;
	}
	cout<<endl;
}

int main(){
    cout<<"****************创建****************"<<endl;
    node* list=create(6);
    traverse(list);  

/*
    cout<<"****************反转****************"<<endl;
    reverse(list);
    traverse(list);

    node* list2=create(2);
    traverse(list2);
    reverse(list2);
    traverse(list2);
    
    node* list3=create(1);
    traverse(list3);
    reverse(list3);
    traverse(list3);
    
    node* list4=create(0);
    
    cout<<"****************删除孤立节点****************"<<endl;
    deleteNodeInList(list->next->next);
    traverse(list);

    cout<<"**************** 检测环 | 找出环的入口节点 ****************"<<endl;
    if(hasLoop(list)==NULL)
        cout<<"无环"<<endl; 
    else
        cout<<"有环"<<endl; 
    
    //奇数(3)长度环 
    node* n1=new node;
    node* n2=new node;
    node* n3=new node;
    node* n4=new node;
    n1->data=1;
    n2->data=2;
    n3->data=3;
    n4->data=4;
    n1->next=n2;
    n2->next=n3;
    n3->next=n4;
    n4->next=n2;

    if(hasLoop(n1)==NULL)
        cout<<"无环"<<endl; 
    else
        cout<<"有环"<<endl; 
    
    node* inter=getLoopHead(n1);
    cout<<"环入口: "<<inter->data<<endl;
    
    delete n1;
    delete n2;
    delete n3;
    delete n4;
    
    //偶(2)长度环 
    n1=new node;
    n2=new node;
    n3=new node;
    n4=new node;
    n1->data=1;
    n2->data=2;
    n3->data=3;
    n4->data=4;
    n1->next=n2;
    n2->next=n3;
    n3->next=n4;
    n4->next=n3;
    
    if(hasLoop(n1)==NULL)
        cout<<"无环"<<endl; 
    else
        cout<<"有环"<<endl; 
    
    inter=getLoopHead(n1);
    cout<<"环入口: "<<inter->data<<endl;
    
    delete n1;
    delete n2;
    delete n3;
    delete n4;
*/

    cout<<"****************寻找倒数第k个节点****************"<<endl;    
    node* last0=findLastK(list,0);
    cout<<last0->data<<endl;
    
    node* last1=findLastK(list,1);
    cout<<last1->data<<endl;
    
    node* last3=findLastK(list,3);
    cout<<last3->data<<endl;
    
    node* last4=findLastK(list,4);
    cout<<last4->data<<endl;
    
    
    system("pause");
    return 0;
}
分享到:
评论

相关推荐

    单向链表 代码架构

    单向链表是一种基本的数据结构,它在计算机科学和编程中有着广泛的应用。与数组不同,链表中的元素不是在内存中连续存储的,而是通过指针或引用连接在一起,形成一个逻辑上的线性序列。单向链表的每个节点包含两部分...

    单向链表类模板_单向链表类模板_fastchq_

    单向链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在C++编程中,为了实现通用性,我们通常会使用模板类来创建单向链表,以便它可以处理不同类型的元素。标题"单向链表类...

    实验二 单向链表的有关操作.cpp

    1.随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。 2.遍历单向链表。 3.把单向链表中元素逆置(不允许申请新的结点空间)。 4.在单向链表中删除所有的偶数元素结点。 5.编写在非递减...

    04.单向链表以及单向链表的应用.ppt

    04.单向链表以及单向链表的应用.ppt

    单向链表源代码

    单向链表是一种基本的数据结构,它在计算机科学中被广泛应用,特别是在算法和数据结构的实现中。在Java编程中,单向链表通常通过定义一个节点类来实现,每个节点包含数据和指向下一个节点的引用。下面我们将深入探讨...

    C#单向链表的实现

    本文将详细讲解如何在C#中实现单向链表,结合源码解析来帮助你深入理解其内部机制。 首先,我们要知道什么是单向链表。单向链表是由一系列节点组成,每个节点包含两个部分:数据域和指针域。数据域存储实际的数据,...

    单向链表实验报告(数据结构)

    实验使用VC++ 6.0作为编程工具,旨在通过实践来深入理解和掌握单向链表的相关操作。 实验目的: 1. 掌握单向链表的存储结构和实现方式。单向链表的每个节点由数据域和指针域组成,指针域指向下一个节点。在内存中,...

    Java 单向链表 插入与删除节点

    这是一个单向链表,它具有插入与删除节点的功能。Entry类实现了链表的各节点。

    Java SE程序 类实现单向链表

    Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现单向链表Java SE程序 类实现...

    将一个单向链表反向连接

    将一个单向链表反向连接

    C语言自学链表,单向链表,双向链表,适合新手学习。

    本资源提供的是针对初学者设计的链表学习材料,包括单向链表和双向链表的实现。下面将详细讲解这两种链表的数据结构及其操作。 1. **单向链表**: 单向链表是一种线性数据结构,每个节点包含两部分:数据域和指针...

    数据结构 单向链表 双向链表 源程序

    本文将深入探讨两种重要的线性数据结构——单向链表和双向链表,以及它们在实际编程中的应用。 单向链表是一种线性数据结构,它的每个元素(称为节点)包含两部分:数据域,用于存储实际的数据;指针域,用于存储下...

    C语言实现的单向链表和双向链表

    本主题将深入探讨由C语言实现的单向链表(slist.h)和双向链表(blist)。这两种链表各有特点,适用于不同的场景,对于理解和掌握数据结构与算法至关重要。 ### 单向链表(slist.h) 单向链表是一种线性数据结构,...

    单向链表.cpp 单向链表实现 包括类定义与测试

    单向链表类定义及测试文件 对应于数据机构与算法分析(c++版)第三版或第二版 作者Clifford A.Shaffer 重庆大学使用教材

    flash as3.0 实现的单向链表

    在IT领域,数据结构是编程基础中的重要组成部分,而单向链表作为基本的数据结构之一,在许多场景下都有着广泛的应用。本项目以Flash AS3.0为编程语言,实现了一个单向链表的数据结构,这对于理解和应用单向链表概念...

    C#单向链表C#单向链表C#单向链表

    单向链表是一种基本的数据结构,它在计算机科学和编程,特别是C#中扮演着重要角色。单向链表与数组不同,不提供随机访问,但允许高效地插入和删除元素,尤其在列表的中间或末尾。接下来,我们将深入探讨C#中单向链表...

    单向链表多种功能实现

    单向链表是一种基本的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在本文中,我们将深入探讨如何实现单向链表的各种操作,包括建立链表、添加元素、删除元素、翻转链表(包括递归方法)...

    C语言实现单向链表及操作

    数据结构,c语言实现的单向链表。代码分享 struct LinkNode { int data; struct LinkNode *next; }; typedef struct LinkNode *Lnode;

    C++单向链表的实现

    C++进阶学习——单向链表的实现,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/49685199

    java语言模拟单向链表

    java语言模拟单向链表,JAVA数据结构

Global site tag (gtag.js) - Google Analytics