• 用类模板封装链表


    闲来无聊,用类的模板封装的链表,记录下来,说不定哪天用得上那。

    template <typename VALUE_TYPE>

    class List
    {
    public:
    //定义节点类型
    typedef struct Node
    {
    VALUE_TYPE data;    //数据域
    struct Node *next;  //指针域:直接后继的指针
    // struct Node *prior; //指针域:直接前驱的指针

    } Node,*LINK_LIST;


    private:
    LINK_LIST ll;   //链表的头指针
    LINK_LIST tail; //尾节点指针
    int size;       //链表长度

    public:
    //构造函数:创建一个空链表(带头结点)
    List()
    {
    ll=(struct Node*)malloc(sizeof(struct Node));
    ll->next=NULL;

    tail=ll;
    size=0;
    }


    //析构函数:销毁链表
    ~List()
    {
    struct Node *p=ll,*q=NULL;

    while(p!=NULL)
    {
    q=p->next;
    free(p);
    p=q;
    }

    ll=NULL;
    tail=NULL;
    size=0;
    }


    //判断链表是否为空
    int IsEmpty()
    {
    return (int)(ll->next);
    }

    //获取链表长度,即节点个数
    int GetLength()
    {
    /*
    struct Node *p=ll->next;
    int cnt=0;


    while(p!=NULL)
    {
    cnt++;
    p=p->next;
    }

    return cnt;
    */
    return size;
    }

    //尾部插入节点
    void Append(VALUE_TYPE v)
    {
    struct Node *q=(struct Node*)malloc(sizeof(struct Node));
    q->data=v;
    q->next=NULL;

    tail->next=q;
    tail=q;
    size++;
    /*
    struct Node *p=ll;

    while(p->next!=NULL)
    {
    p=p->next;
    }

    p->next=q;
    */
    }


    //头部插入节点
    void InsertHead(VALUE_TYPE v)
    {
    struct Node *q=(struct Node*)malloc(sizeof(struct Node));
    q->data=v;
    q->next=ll->next;

    if(ll->next==NULL) tail=q;
    ll->next=q;

    size++;
    }


    //在任意位置处插入节点
    int Insert(int pos,VALUE_TYPE v)
    {
    struct Node *p=ll;
    int i=0;

    while(p!=NULL && i<pos-1)
    {
    p=p->next;
    i++;
    }

    if(p==NULL || i>pos-1) return 0;

    struct Node *q=(struct Node*)malloc(sizeof(struct Node));
    q->data=v;
    q->next=p->next;

    p->next=q;
    size++;

    return 1;
    }


    //删除指定节点,根据节点索引(即节点位置,头结点的索引为0,第一个节点的索引为1,以此类推)
    int Delete(int pos,VALUE_TYPE *v)
    {
    struct Node *p=ll;
    int i=0;

    while(p!=NULL && i<pos-1)
    {
    p=p->next;
    i++;
    }

    //pos大于链表长度或小于1就失败返回
    if(p==NULL || i>pos-1) return 0;

    if(NULL!=v) *v=p->next->data;

    if(p->next==tail) tail=p;

    /*
    struct Node *q=p->next->next;
    free(p->next);
    p->next=q;
    */
    //和上面的处理等效
    struct Node *q=p->next;
    p->next=q->next;
    free(q);
    size--;

    return 1;
    }


    //删除指定节点,根据节点的数据域,删除成功返回被删除节点的索引,否则返回0
    int Delete(VALUE_TYPE v)
    {
    struct Node *p=ll;
    int pos=1;

    while(p->next!=NULL && p->next->data!=v) //此时&&的两个操作数不能颠倒位置
    {
    pos++;
    p=p->next;
    }


    //如果没有找到满足条件的节点就失败返回
    if(p->next==NULL) return 0;

    if(p->next==tail) tail=p;

    /*
    struct Node *q=p->next->next;
    free(p->next);
    p->next=q;
    */

    //和上面的处理等效
    struct Node *q=p->next;
    p->next=q->next;
    free(q);

    size--;
    return pos;
    }


    //修改指定节点,根据索引
    int UpdateByIndex(int pos,VALUE_TYPE v)
    {
    struct Node *p=ll;
    int i=0;

    while(p!=NULL && i<pos)
    {
    p=p->next;
    i++;
    }

    //pos大于链表长度或小于1就失败返回
    if(p==NULL || i>pos-1) return 0;

    p->data=v;
    return 1;
    }


    //修改指定节点,根据数据值
    //修改成功返回被修改节点的索引,否则返回0
    int UpdateByValue(VALUE_TYPE old_v,VALUE_TYPE new_v)
    {
    struct Node *p=ll->next;
    int i=1;

    while(p!=NULL && p->data!=old_v)
    {
    p=p->next;
    i++;
    }


    if(p==NULL) return 0;

    p->data=new_v;

    return i;
    }


    //查找指定节点,根据索引获取数据值
    VALUE_TYPE* GetElemByIndex(int index)
    {
    struct Node *p=ll;
    int i=0;

    while(p!=NULL && i<index)
    {
    p=p->next;
    i++;
    }

    //pos大于链表长度或小于1就失败返回
    if(p==NULL || i>index-1) return NULL;

    return &(p->data);
    }


    //查找指定节点,根据数据值获取索引值
    int GetElemByValue(VALUE_TYPE v)
    {
    struct Node *p=ll->next;
    int i=1;


    while(p!=NULL && p->data!=v)
    {
    p=p->next;
    i++;
    }

    if(p==NULL) return 0;

    return i;
    }


    //遍历链表
    void Traverse(int(*visit)(VALUE_TYPE*))
    {
    struct Node *p=ll->next;

    while(p!=NULL)
    {
    if(!visit(&(p->data))) break;
    p=p->next;
    }
    }


    //排序
    //时间复杂度:O(n*n)
    void Sort(int (__cdecl *compare )(const VALUE_TYPE &elem1, const VALUE_TYPE &elem2 ))
    {
    int i,j;
    Node *p=NULL;
    VALUE_TYPE v;

    for(i=0;i<size-1;i++)
    {
    p=ll->next;


    for(j=0;j<size-i-1;j++)
    {
    if(compare(p->data,p->next->data))
    {
    memcpy(&v,&(p->data),sizeof(VALUE_TYPE));
    memcpy(&(p->data),&(p->next->data),sizeof(VALUE_TYPE));
    memcpy(&(p->next->data),&v,sizeof(VALUE_TYPE));
    }

    p=p->next;
    }
    }
    }


    //逆序
    //时间复杂度:O(n)
    void Reverse()
    {
    /*
    //算法一:相邻节点依次反向
    Node* p=ll->next;
    Node* q=p->next;
    Node* t=NULL;

    while(q!=NULL)
    {
    t=q->next;
    q->next=p;
    p=q;
    q=t;
    }


    ll->next->next=NULL;
    ll->next=p;
    */


    //算法二:从第二个节点开始依次插入到链表头
    Node* p=ll->next->next;
    Node* q=NULL;

    //逆序前的第一个节点处理后变为尾节点,所以它的next要赋值为NULL
    ll->next->next=NULL;

    while(p!=NULL)
    {
    q=p->next;
    p->next=ll->next;
    ll->next=p;
    p=q;
    }
    }


    //合并
    //时间复杂度:O(1)
    void Merge(List& l)
    {
    tail->next=l.ll->next;
    tail=l.tail;

    l.ll->next=NULL;

    /*
    Node *p=l.ll->next;


    while(p!=NULL)
    {
    tail->next=p;
    tail=p;

    p=p->next;
    }
    */
    }

    };


    以上链表经本人测试没有问题。

    Do one thing at a time,and do well.
  • 相关阅读:
    Ajax
    对于本地上关联了远程的git上的项目,删除现有的关联,然后关联新创建的git项目
    UNI-APP_uni-simple-router的快速上手(路由,nui路由拦截)
    js之观察者模式和发布订阅模式区别
    Vue CLI 3.0脚手架如何在本地配置mock数据
    es6解构赋值和扩展运算符
    js Array数组详细操作方法及解析合集
    list排序
    java常用的object数据处理
    java 读写 txt 文件
  • 原文地址:https://www.cnblogs.com/huiz/p/9610694.html
Copyright © 2020-2023  润新知