zoukankan      html  css  js  c++  java
  • 数据结构算法——链表的各种操作,C++和Python

    时隔已久,一直没更新博客,感觉很愧疚呀。

    先贴上所有的代码。这个是用C++写的

    #include "stdafx.h"
    
    //Author:Albert
    //Date: 2018.10.28
    
    #include<iostream>
    using namespace std;
    
    typedef int datatype;
    class Node
    {
    public:
        int data;
        Node *next;
    };
    
    class linkList
    {
    public:
        linkList();//初始化一个单链表
        ~linkList();//销毁一个单链表
        bool creatLinkListByInput(int n);//通过控制台输入新建一个长度为n的单链表
        void dispLinkList();//把链表里储存的数据都显示出来
        int getLength();
        void insertNodetoEnd(datatype data);
        void insertNode(datatype data, int n);//在第n个数据后插入一个数据data
        void DeleteNode(int n);//删除第n个节点
        void Reverse();
    private:
        Node * head;
    };
    
    linkList::linkList()
    {
        head = new Node;
        head->data = 0;
        head->next = NULL;
    }
    linkList::~linkList()
    {
        delete head;
    }
    bool linkList::creatLinkListByInput(int n)
    {
        Node *pnew, *ptemp;
        ptemp = head;
        if (n < 0) { cout << "error" << endl; return false; }
        for (int i = 0;i < n;i++)
        {
            pnew = new Node;
            cout << "请输入第" << i + 1 << "个值:";
            cin >> pnew->data;
            pnew->next = NULL;
            ptemp->next = pnew;
            ptemp = pnew;
        }
        return true;
    }
    void linkList::dispLinkList()
    {
        Node *p;
        p = head;
        if (p!=NULL)
        {
            while (p->next!=NULL)
            {
                p = p->next;
                cout << p->data << endl;
            }
        }
        else
        {
            cout << "这是一个空链表" << endl;
        }
    }
    
    int linkList::getLength()
    {
        int n=0;
        Node *p;
        p = head;
        while (p->next!=NULL)
        {
            n++;
            p = p->next;
        }
        return n;
    }
    
    void linkList::insertNodetoEnd(datatype data)
    {
        Node *pnew=new Node;
        pnew->data = data;
        pnew->next = NULL;
    
        Node *p=head;
        while (p->next != NULL)
        {
            p = p->next;
        }
        p->next = pnew;
    }
    
    void linkList::insertNode(datatype data, int n)
    {
        Node *p = head;
        Node *pnew = new Node;
        for (int i = 0;i < n;i++)
        {
            p = p->next;
        }
        //此时p指向的是第n个数据
        pnew->data = data;
        pnew->next = p->next;
        p->next = pnew;
    }
    
    void linkList::DeleteNode(int n)
    {
        Node *p = head;
        Node *ppre = new Node;
        for (int i = 0;i < n;i++)
        {
            ppre = p;
            p = p->next;
        }
        //ppre是要删除的节点的前一个节点
        ppre->next = p->next;
        delete p;
    }
    
    void linkList::Reverse()
    {
        
        Node *plast = head->next;
        Node *p = plast->next;
        Node *ptmp = new Node;
        plast->next = NULL;
        while (p->next != NULL)
        {
            ptmp = p;
            p = p->next;
            ptmp->next = plast;
            plast= ptmp;
        }
        p->next = plast;
        head->next = p;
    }
    
    
    int main()
    {
        linkList a;
    
        //新建一个长度为3的单链表
        a.creatLinkListByInput(3);
        a.dispLinkList();
        cout << "链表长度为:" << a.getLength() << endl;
    
    
        cout << "在尾部插入一个1:" << endl;
        a.insertNodetoEnd(1);
        a.dispLinkList();
        cout << "链表长度为:" << a.getLength() << endl;
    
    
        cout << "在第2个数据后插入1:" << endl;
        a.insertNode(1,2);
        a.dispLinkList();
        cout << "链表长度为:" << a.getLength() << endl;
    
        cout << "删除第4个数据" << endl;
        a.DeleteNode(4);
        a.dispLinkList();
        cout << "链表长度为:" << a.getLength() << endl;
    
        cout << "将链表逆置" << endl;
        a.Reverse();
        a.dispLinkList();
    
    
    
        return 0;
    }

    1、新建一个单链表

    bool linkList::creatLinkListByInput(int n)
    {
        Node *pnew, *ptemp;
        ptemp = head;
        if (n < 0) { cout << "error" << endl; return false; }
        for (int i = 0;i < n;i++)
        {
            pnew = new Node;
            cout << "请输入第" << i + 1 << "个值:";
            cin >> pnew->data;
            pnew->next = NULL;
            ptemp->next = pnew;
            ptemp = pnew;
        }
        return true;
    }

    这个代码还是我看了别人的之后才写的。在控制台输入一系列数据,返回是否新建成功。

    其中最关键的一处就是定义一个head节点。这个节点不储存数据,head->next才是第一个储存的数据。

    这样的话就比较好写循环里的内容了,后面的调用也很方便。

    用图画一下就很容易理解了。

     

    显示整个链表数据,得到链表长度什么的,不用多说啦。直接遍历就行。

    2、插入节点。

    void linkList::insertNode(datatype data, int n)
    {
    Node *p = head;
    Node *pnew = new Node;
    for (int i = 0;i < n;i++)
    {
    p = p->next;
    }
    //此时p指向的是第n个数据
    pnew->data = data;
    pnew->next = p->next;
    p->next = pnew;
    }

    先遍历到到第n个节点

    然后

    3、删除一个节点

    void linkList::DeleteNode(int n)
    {
        Node *p = head;
        Node *ppre = new Node;
        for (int i = 0;i < n;i++)
        {
            ppre = p;
            p = p->next;
        }
        //ppre是要删除的节点的前一个节点
        ppre->next = p->next;
        delete p;
    }

     把它画出来就是

    4、单链表的逆置

    void linkList::Reverse()
    {
        
        Node *plast = head->next;
        Node *p = plast->next;
        Node *ptmp = new Node;
        plast->next = NULL;
        while (p->next != NULL)
        {
            ptmp = p;
            p = p->next;
            ptmp->next = plast;
            plast= ptmp;
        }
        p->next = plast;
        head->next = p;
    }

     这里ptmp的作用就是为了防止p->next=plast从而导致无法往下遍历。

    我见还有一种用ppre,p,pnex三个指针的。思想跟这个差不多。

    感觉自己菜的要死,只能从头再开始学啦。

    还有几个问题

    链表中环的检测:用的快慢指针的思想。

    两个有序链表的合并:遍历,主要是别让指针指乱了。

    删除链表倒数第n个节点。如果链表长度知道,就很简单了,转化为整数就好。如果长度不知道,我觉得,就用迭代可以有。

    求链表中的中间节点,用快慢针呀。

    这几个问题我没时间一个一个的写啦。以后遇到了在一个一个的写。

    此外还有循环链表和双向链表,他们都各有千秋,懂的单链表,这都很简单了。

    以下为我看了Python写的之后的追加

    最近贼以下把它封装成一个类,嘿嘿嘿。面向对象编程感觉条理贼清晰

    #!/user/bin/python3
    # -*- coding:utf-8 -*-
    #@author:Albert
    #@time:2018/11/3
    
    class Node(object):
        def __init__(self,x):
            self.data=x
            self.next=None
    
    class Linklist():
        def __init__(self,l):
            self.head=Node(0)
            self.changeLinklistTo(l)
        def changeLinklistTo(self,l):
            p=self.head
            for i in l:
                p.next=Node(i)
                p=p.next
        def display(self):
            p=self.head.next
            while(p):
                print(p.data)
                p=p.next
        def reverse(self):#翻转整个链表
            cur,prev=self.head.next,None
            while cur:
                cur.next,prev,cur=prev,cur,cur.next
            self.head.next=prev
        def swapPairs(self):#交换相邻的两个链表节点位置
            pre=self.head
            while pre.next and pre.next.next:
                a=pre.next
                b=pre.next.next
                pre.next,b.next,a.next=b,a,b.next  #此处多重赋值是先计算右边,然后统一赋给左边
                pre=a
        def hasCycle(self):#检测单链表环,用的快慢针的思想
            fast=slow=self.head.next
            while fast and slow and fast.next:
                slow=slow.next
                fast=fast.next.next
                if fast is slow:
                    return True
            return False
    a=Linklist([1,2,3,4,5,6])
    a.display()
    a.reverse()
    print("A has been reversed")
    a.display()
    a.swapPairs()
    print("A has been swapped")
    a.display()
    
    print("A has cycle? : ",a.hasCycle()) 

  • 相关阅读:
    第二阶段团队冲刺第五天
    第二阶段冲刺七
    第二阶段冲刺六
    第二阶段冲刺五
    第二阶段冲刺四
    冲刺第二阶段三
    冲刺第二阶段二
    冲刺第二阶段 一
    项目总结
    第二阶段SCRUM
  • 原文地址:https://www.cnblogs.com/albert-yzp/p/9866453.html
Copyright © 2011-2022 走看看