数据结构——线性表

Posted noneplus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——线性表相关的知识,希望对你有一定的参考价值。

什么是线性表?

线性表是具有相同类型的n个元素(n>=0)的有限序列

1.顺序表

  • 线性表采用顺序存储方式
  • 其逻辑顺序和物理顺序相同

问题:需要连续存储空间,插入等操作需要移动大量元素,时间复杂度高。

2.单链表

线性表采用链式存储方式称为单链表。

链式存储是采用节点来进行存储的。

每个节点包括data域和next域。(不一定连续存储)
技术图片

  • 单链表反转
  • 单链表的增删改查
  • 约瑟夫环

单链表反转

技术图片

技术图片

单链表的增删改查

import java.util.Stack;

//定义单个节点
class Node


    public String data;  //定义数据节点

    public Node next;   //定义指向下一个节点的指针

    public Node() 
    

    public Node(String data) 
        this.data = data;
    

    public String getData() 
        return data;
    

    public void setData(String data) 
        this.data = data;
    

    public Node getNext() 
        return next;
    

    public void setNext(Node next) 
        this.next = next;
    

    @Override
    public String toString() 
        return "Note" +
                "data='" + data + '\\'' +
                '';
    



public class Operation

    //初始化头结点
    private static Node head = new Node();


    private static Node reverseHead = new Node();


    //插入节点(头插)
    public void insertToHead(Node node)
    
        Node temp = head;

        //头插法需要设置head.next和node.next的值。其中nodeNext指向headNext,而headNext指向node。
        //由于是赋值的关系,二者顺序不可颠倒
        node.next=temp.next;
        temp.next=node;
    

    //插入节点(尾插)
    public void insertToLast(Node node)
    
        Node temp = head;

        while (true)
        
            if(temp.next==null)
            break;
            temp=temp.next;
        
        temp.next=node;
    

    //插入节点(指定位置k之后)

    public void insertToK(Node node,int k)
    
        Node temp = head;
        for(int i=0;i<k;i++)
        
            temp=temp.next;
        
        node.next=temp.next;
        temp.next=node;
    


    //删除第m个节点
    public void deleteM(int m)
    
        Node temp = head;
        for(int i=0;i<m-1;i++)
        
            temp=temp.next;
        
        temp.next=temp.next.next;
    


    //修改第n个节点(n)
    public void updateN(int n)
    
        Node temp = head;
        for(int i=0;i<n;i++)
        
            temp=temp.next;
        
        temp.data="up";
    


    //递归反转

    public Node reverseLinkedList(Node node) 
        if (node == null || node.next == null) 
            return node;
         else 
            Node headNode = reverseLinkedList(node.next);
            node.next.next = node;
            node.next = null;
            return headNode;
        
    

    //遍历反转
    public Node reserveByFor(Node head)
    
        Node cur = head.next;
        Node next = null;
        Node Rhead = new Node();


        while(true)
        
            if(cur==null)
            
                break;
            
            else
            
                next=cur.next;
                cur.next=Rhead.next;
                Rhead.next=cur;

                cur=next;
            
        

        head.next=Rhead.next;

        return head;
    

    //print(last to first)
    public void printLtoF(Node head)
    
        Stack<Node>stack = new Stack<>();
        Node cur = head.next;
        while (cur!=null)
        
            stack.push(cur);
            cur=cur.next;
        
        while (stack.size()>0)
        
            System.out.println(stack.pop());
        
    




    public static void main(String[] args)
    
        Operation operation = new Operation();

        operation.insertToHead(new Node("A"));
        operation.insertToHead(new Node("B"));
        operation.insertToHead(new Node("C"));

        operation.insertToLast(new Node("1"));
        operation.insertToLast(new Node("2"));
        operation.insertToLast(new Node("3"));

//        operation.insertToK(new Node("k"),2);

//        operation.deleteM(3);

//        operation.updateN(1);


        Node temp =head;
        //遍历链表
        while(true)
        
            if(temp.next==null)
            break;
            else
            
                temp=temp.next;
                System.out.println(temp.toString());

            
        



        System.out.println("//1.求单链表中有效节点个数.");

        temp=head;
        int count=0;
        while(true)
        
            if(temp.next==null)
            break;
            else
            
                temp=temp.next;
                count++;
            
        
        System.out.println(count);


        System.out.println("//2.查找单链表中倒数第K=3个节点");

        temp=head;

        //获取链表总长
        int length=0;

        while (true)
        
            if(temp.next==null)
            break;
            else
            
                temp=temp.next;
                length++;
            
        


        temp=head;
        for(int i=0;i<length-2;i++)
        
            temp=temp.next;
        
        System.out.println(temp.data);


        System.out.println("3.实现单链表的反转");

//      temp=operation.reverseLinkedList(head);


        temp = operation.reserveByFor(head);

        //遍历链表
        while(true)
        
            if(temp.next==null)
            break;
            else
            
                temp=temp.next;
                System.out.println(temp.toString());
            
        


        System.out.println("4.从尾到头打印单链表");

        temp = head;
        operation.printLtoF(temp);






    

技术图片

单向环形链表输出约瑟夫环

技术图片

//定义单个节点
class Node


    public String data;  //定义数据节点

    public Node next;   //定义指向下一个节点的指针


    public Node() 
    

    public Node(String data) 
        this.data = data;
    


    @Override
    public String toString() 
        return "Note" +
                "data='" + data + '\\'' +
                '';
    





public class Operation

    //初始化头结点
    private static Node head = new Node();

    //尾插法
    public void add(Node node)
    
        Node temp = head;

        while (true)
        
            if(temp.next==null)
            break;
            temp=temp.next;
        
        temp.next=node;
    

    //创建单向环形链表
    public Node createCircle(int n)
    
        //创建单链表
        for(int i=0;i<n;i++)
        
            add(new Node("No:"+(i+1)));
        

        //遍历链表
        Node temp = head;
        while(temp.next!=null)
        
            temp=temp.next;
            System.out.println(temp);
        

        Node last = temp;
        temp=head;
        last.next=head.next;   //连接首尾

        System.out.println("last为最后一个数5:");
        System.out.println(last);


        System.out.println("循环两遍单向环形链表:");
        int count=2*n;
        while(last!=null)
        
            if(count==0)
            
                break;
            
            System.out.println(last.next);
            last=last.next;
            count--;
        
        System.out.println("last="+last.data);
        return last;
    

    public static void JosephusProblem(int n, int k, int m, Node last)
    
        //定位到第k个节点,输出k+1个节点并删除,并让last定位到第k个节点

        Node temp = last;
        for(int i=0;i<k;i++)  //定位到第k个节点
        
            temp=temp.next;
        
        System.out.println("第一次输出"+temp.next.data);//输出

        temp.next=temp.next.next; //删除第K+1个节点
        last=temp.next;



        for(int i=0;i<n-1;i++)
        
            temp=last;

            System.out.println("第二次输出"+temp.next.data);

            temp.next=temp.next.next;
            last=temp.next;
        


    
    public static void main(String[] args)
    
        Operation operation = new Operation();

        //定义人数
        int n=5;
        Node last = operation.createCircle(n);


        //定义从第几个节点开始数
        int k=1;
        //定义数的次数
        int m=2;


        System.out.println("输出约瑟夫环:");
        JosephusProblem(n,k,m,last);


    

技术图片

3.双向链表

双向链表与单向链表的区别

单向列表只能从前往后查找,而双向链表可以向前向后查找。
单向链表删除节点需要依靠辅助节点,而双向链表可以实现自我删除。

双向链表与单项列表的实际区别在于多了一个pre域。

技术图片

双向链表增删改查

import java.util.Stack;

//定义单个节点
class Node


    public String data;  //定义数据节点

    public Node next;   //定义指向下一个节点的指针

    public Node pre;    //定义指向上一个节点的指针

    public Node() 
    

    public Node(String data) 
        this.data = data;
    


    @Override
    public String toString() 
        return "Note" +
                "data='" + data + '\\'' +
                '';
    



public class Operation

    //初始化头结点
    private static Node head = new Node();


    //插入节点(尾插法)
    public void addNode(Node node)
    
        Node temp = head;
        while(true)
        
            if(temp.next==null)
            
                break;
            
            temp=temp.next;
        
        temp.next=node;
        node.pre=temp;
    

    //插入节点(头插法)
    public void addNodeToHead(Node node)
    
        Node temp = head;


        node.pre=temp;
        node.next=temp.next;
        temp.next.pre=node;
        temp.next=node;
    

    //插入到第k个节点后
    public void addToK(Node node,int k)
    
        Node temp = head;
        for(int i=0;i<k;i++)
        
            temp=temp.next;
        
        //先建立单链表联系
        node.next=temp.next;
        temp.next=node;
        //建立pre指向
        node.pre=temp;
        node.next.pre=node;
    

    //删除第n个结点
    public void deleteNode(int n)
    
        Node temp = head;
        for(int i=0;i<n;i++)
        
            temp=temp.next;
        
        temp.next.pre=temp.pre;
        temp.pre.next=temp.next;
    

    public void list()
    
        //遍历链表
        Node temp = head;
        while(temp.next!=null)
        
            temp=temp.next;
            System.out.println(temp.toString());
        
        System.out.println("=============");
    


    //修改第m个结点
    public void update(int m)
    
        Node temp = head;
        for(int i=0;i<m;i++)
        
            temp=temp.next;
        
        temp.data="up";
    

    public static void main(String[] args)
    
        Operation operation = new Operation();

        operation.addNode(new Node("A"));
        operation.addNode(new Node("B"));
        operation.addNode(new Node("C"));
        operation.addNode(new Node("D"));
        operation.addNodeToHead(new Node("head1"));
        operation.addNodeToHead(new Node("head2"));
        operation.addNodeToHead(new Node("head3"));

        //遍历链表
        operation.list();

        System.out.println("删除第n个节点");
        operation.deleteNode(3);

        //遍历链表
        operation.list();

        System.out.println("修改第m个节点");

        operation.update(3);

        operation.list();

        System.out.println("插入到第k个节点后");
        operation.addToK(new Node("k" ),3);

        operation.list();
    

以上是关于数据结构——线性表的主要内容,如果未能解决你的问题,请参考以下文章

数据结构-线性表

数据结构:线性表

数据结构线性表之实现单链表

数据结构c语言版 使用线性表的顺序储存结构定义(静态)实现线性表的初

数据结构 线性表-顺序表的应用?

Java数据结构(线性表)--线性表 & 线性表和数组的关系