• 数据结构(C++)——链表


    顺序表和链表的比较

      1.存取方式

        顺序表可以随机访问,而链表只能从表头顺序查找。(因此经常查找顺序表某一个元素时,顺序表更适合)

      2.逻辑结构与物理结构

        顺序表中,逻辑上相邻的元素,其物理存储位置也相邻。链表中,逻辑相邻的元素,其物理存储位置不相邻。

      3.查找、插入和删除操作

        按值查找时,顺序表链表时间复杂度都为O(n)。

        按序号查找时,顺序表时间复杂度为O(1),而链表时间复杂度为O(n)。

        插入和删除元素中,顺序表平均移动半个表的长度,而链表只需要改变一下指针域的值就可以了。

        (因此,当线性表经常进行插入和删除元素时,选链表更合适)

      4.空间分配

        顺序表在静态存储分配的情形下,存储空间装满了就不能扩充;链表就不存在这个问题。

    链表结构

    typedef int ElemType; 
    
    typedef struct Node{
        ElemType data;
        struct Node *next;    
    }*LinkList,*PNode;

    头插法创建单链表

    LinkList HeadInsertList(LinkList L){
        //头插法创建单链表,头插法简单,但元素的顺序是插入顺序的逆序 
        L=new Node;    //分配头节点空间 
        L->next=NULL;  //头结点的next指针刚开始指向NULL 
        
        if(!L){        //分配失败时,返回NULL 
            return L;
        }
        
        LinkList s; 
        ElemType x;
        cin>>x;
        while(x!=9999){     //输入9999停止输入 
            s=new Node;    //插入的节点 
            if(!s){
                cout<<"内存分配失败!"<<endl;
                return NULL; 
            }
            
            s->data=x;
            s->next=L->next;
            L->next=s;
            
            cin>>x;
        }
        
        return L;
    }

    尾插法创建单链表

    LinkList TailInsertList(LinkList L){
        //尾插法创建单链表,链表的顺序和插入顺序一样,但需要尾指针
        L=new Node;
        if(!L){
            cout<<"内存分配失败!"<<endl; 
            return L;
        }
        
        LinkList r,s;
        r=L;            //r为尾节点,每次指向最后一个节点 
        
        ElemType x;
        cin>>x;
        while(x!=9999){
            s=new Node;
            if(!s){
                cout<<"内存分配失败!"<<endl;
                return NULL;
            }
            
            s->data=x;
            r->next=s;
            r=s;
            
            cin>>x;
        } 
        r->next=NULL;   //最后要将尾节点指针指控 
        
        return L;
    } 

    按序号返回节点的指针

    PNode GetElem(LinkList L,int i){
        //按序号返回节点的指针
        int j=0;     //刚开始p指向头节点 
        PNode p=L;
        
        if(i<0){
            return NULL;    
        }
         
         while(j<i&&p!=NULL){  //节点和序号一起移动 
             p=p->next;
             j++;
         }  
         
         return p;  //查找失败时,p为NULL 
    }

    返回链表中第一个元素为e节点的指针

    PNode FindElem(LinkList L,ElemType e){
        //返回链表中第一个元素为e节点的指针
        PNode p=L->next;
         
         while(p&&p->data!=e){  //从第一个节点开始,元素不为e时,就向后推一位 
             p=p->next;
         }
         
         return p;   //没找到元素时,返回NULL 
    } 

    将e插入第i个节点上

    void InsertList(LinkList L,ElemType e,int i){
        //将e插入第i个节点上
        PNode p=GetElem(L,i-1);  //找到前驱元的位置
        if(!p){
            return ;
        } 
        
        PNode s;
        s=new Node;
        if(s==NULL){
            cout<<"内存分配失败!"<<endl;
            return ;
        } 
        
        s->data=e;
        s->next=p->next;
        p->next=s;
    } 

    删除第i个节点

    void DeleteList(LinkList L,int i){
        //删除第i个节点
        PNode p=GetElem(L,i-1);
        PNode q=p->next;
        p->next=q->next;
        delete q; 
        
    }

    求链表的长度

    int LengthList(LinkList L){
        //求链表的长度
        PNode p=L;
        int i=0;    //计数器变量 
        
        if(L==NULL){
            return 0;
        }
        
        while(p->next!=NULL){
            p=p->next;
            i++;
        } 
        
        return i;
    }

    利用递归删除链表中值为x的节点

    void Delete1(LinkList &L,ElemType x){
        //利用递归删除链表中值为x的节点
        PNode p;
        
        if(L==NULL){
            return ;
        }
        
        if(L->data==x){
            p=L;
            L=L->next;
            delete p;
            
            Delete1(L,x);
        }else {
            Delete1(L->next,x);
        }
         
    } 

    删除链表中值为x的节点

    void Delete2(LinkList &L,ElemType x){
        //删除链表中值为x的节点
        PNode p=L->next,pre=L,det;
         while(p!=NULL){
             
             if(p->data==x){
                 det=p;         //det指向的是要删除的节点 
                 pre->next=p->next;  //pre指向的是要删除结点的前一个结点 
                 p=p->next; 
                 delete det; 
             }
             else{
                 p=p->next;
                 pre=pre->next;
             }
         } 
    }
  • 相关阅读:
    提升云桌面登录账号安全,宁盾双因素认证“护航”齐鲁制药移动办公
    关于双因素认证(2FA),这些基础知识你一定要知道
    3天时间,如何用双因素认证帮5000名员工实现远程办公账号安全
    企业快速发展,新技术新场景频出,如何构建身份管理体系支撑企业持续发展变革?
    关于ADFS的局限性,你了解多少?
    初创公司如何布局零信任网络安全?
    什么是身份和访问管理(IAM)?
    为什么是时候迎接远程办公了?
    无密码就是最好的密码,深入解析免密认证的方法和实例
    带你了解免密认证的优势和挑战
  • 原文地址:https://www.cnblogs.com/WP-WangPin/p/12741110.html
Copyright © 2020-2023  润新知