常用链表及其必备操作


#常用链表链及其必备操作

单链表的反转算法

思路分析
(1)遍历单链表,获取当前链表的当前结点curNode,并记录当前结点的下一个结点nextNode;
(2) 新建一个反转链表reverseHead,将当前结点curNode插入到reverseHead的最前面的结点(curNode.next=reverseHead.next;reverseHead.next=curNode)
(3) 只要当前链表没有遍历完成(curNode!=null),获取下一个结点为当前结点,重复执行Step1、Step2
代码

 public void reverse(){
        //链表为空或者只有一个结点,则不需要反转
        if(head.next==null || head.next.next==null){
            return ;
        }
        Node reverseHead=new Node(0);//反转结点的head指针;
        Node cur=head.next;//指向原链表的当前结点
        Node next=null;
        while(cur!=null){
            next= cur.next;// 记录当前结点的下一个结点
            cur.next=reverseHead.next;
            reverseHead.next=cur;
            cur=next;
        }
        head=reverseHead;
    }

获取链表中有效节点的个数(不包含头节点)

思路分析: 遍历链表,计数器加一即可

 public int getLength(){
        int count=0;
        Node tmp=head.next;
        while(tmp!=null){
            count++;
            tmp=tmp.next;
        }
        return count;
    }

获取倒数第K个结点

思路分析: 首先获取该链表总的个数Count,则倒数第k个结点即为顺数第Count-k个结点

    public Node getLastIndexNode(int k){
        int count=getLength();
        if(k>count){
            return null;
        }
        Node tmp=head.next;
        int index=1;
        while(index <= count-k){
            index++;
            tmp=tmp.next;
        }
        return tmp;
    }

合并两条有序的单链表,合并之后仍然是有序的

思路分析:
(1)设置两个指针tmp1和tmp2分别指向链表1和链表2
(2)依次比较两个大小,把小的增加到新链表的尾部直到循环退出;
(3)把其中一条没有完成的链表继续连接到tmp的尾部;

 public Node mergeSingleLinkedList(Node head1,Node head2){
       Node tmp1=head1.next;
       Node tmp2=head2.next;
       if(head1.next==null){
           return head2;
       }
       if(head2.next==null){
           return head1;
       }
       Node newHead=new Node(0);
       Node tmp =newHead;
       while(tmp1!=null && tmp2!=null){
            if(tmp1.data>tmp2.data){
                tmp.next=tmp2;
                tmp=tmp2;
                tmp2=tmp2.next;
            }else{
                tmp.next=tmp1;
                tmp=tmp1;
                tmp1=tmp1.next;
            }
       }
       //上面的while循环跳出,必然是有一个先跳出循环
       if(tmp1==null){
           tmp.next=tmp2;
       }else{
           tmp.next=tmp1;
       }
       head=newHead;
       return tmp;
    } 

双向链表

双向链表相对于单向链表的优点
(1)单向链表遍历时,只能先后遍历,而双向链表可以向前遍历
(2)双向链表可以实现自我结点的删除,而单向链表删除某个结点的时候,是删除当前结点的下一个结点

单向环形链表

josehu环问题

由n个结点围城一个环,编号为[1,n],从第k个结点(1<=k<=n)开始,从1开始计数,数到m的结点提取出来,然后再从该节点的下一个结点开始,又从1到m开始数,然后取出来,直到所有的节点都取出来为止,求被取出来的结点的顺序。
解决思路
josehu环问题:假设链环中有5个节点,从1节点开始数,数2次
算法实现步骤:
(1)创建joshu环(含有一个指向第一个节点的指针first)
(2)新建一个curNode指针,让其指向first的前一个结点(curNode.nextfirst)
(3)找到起始点,同时移动first和curNode指针,移动startNo-1次,此操作始终保持curNode.next
first
(4)开始数数,同时移动指针curNode和first的次数为:countNum-1次。
(5)判断curNode==first,如果成立,则进行(6),否则进行(7)
(6)此时环中只剩下最后一个结点,打印该结点信息即可
(7)删除first结点,即first=first.next;curNode.next=fist;继续执行(3)、(4)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言版本的直观链表创建和读取工具,隐藏了链表操作细节 可以非常方便地在单片机等平台做FIFO应用,前提是不要用的太嗨,在极小内存的平台上建立好多个FIFO 支持多线程程序,目前尚未发现BUG /*---------------------------- 版本 : V0.01 作者 : ICARUS 日期 : 2019年6月3日 ------------------------------*/ //--------------------------------------------------------------------------------------------// 内置函数 int SL_Create( ) 创建一个数据链表,返回其在系统内的ID值,创建不成功则返回 SL_R_ERR int SL_Delete(int ID) 删除某个使用SL_Create()函数创建过的链表 int SL_InsertInturn(int ID,char* chain,int len,char ** NewNode) 向链表序号为ID的链表尾部插入chain为首地址,长度为len的数据块,数据块在系统中的内存地址将被NewNode返回,若想得到该内存地址,用(*NewNode) 使用示例: char * NewNode; SL_InsetInturn(5,"Hey,boy",strlen("HeyBoy\r\n"),&NewNode;); printf("%s",*NewNode); //------------------------------------------------------------------------------------------// int SL_ReadInturn(int ID,char * chain) 从链表序号为ID的链表头部读取数据到chain中,若返回值大于0,则返回值为数据长度,否则读取失败或链表中已无数据可读。 这一读操作会把数据节点从链表中移除 使用示例: int ReadLen; char chain[1500]; ReadLen = SL_ReadInturn(5,chain); if(ReadLen > 0) { ..... } 注意:由于时间原因,没有来得及修改SL_NodeModify()函数的实现,代码中注释掉的部分请先不要使用,请等待下一版本发布 使用时配合自定义的数据类型效果更佳。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值