链表的C++实现

▼魔方 西西 提交于 2020-02-06 18:17:18

参考用书《数据结构》(秦锋,汤亚玲主编)
贴下代码:

#include <iostream>
#include <string>
using namespace std;
class Node{
public:
    string data;
    Node * next;
    Node()
    {
        next = NULL;
    }
};
class Link{
public :
    Node *head;//头指针
    Link()//构造函数
    {
        head = NULL;
    }
    ~Link(){//析构函数
        DeleteAll();
    }
    void Initiate(); //初始化
    void DeleteAll(); //删除所有节点
    void HeadCreate(int n);//头插法建表
    void TrailCreate(int n);//尾插法建表
    void HeadCreateWithHead(int n);//建立带表头的链表(从头)
    void TrailCreateWithTrail(int n);//建立带表头的链表(从尾)
    int Length(); //链表长度
    Node *Locatex(string data); //查找值为x的数据元素
    Node *Locatei(int i ); //取第i个元素值
    bool Insert(string data, int i);//在链表第i个元素之前插入x
    bool Deleted(int i); //删除链表中第i个结点
    void Print(); //打印链表
    string Get(int i); //读取第i个位置上的元素值
    void reverse(Link &H); //单链表的倒置
    void merge(Link &A,Link &B,Link &C)
    {
        Node *p, *q, *s;
        p=A.head->next; q=B.head->next; //p、q分别指向两个链表的第一个元素
        C.head->next=NULL;//初始化
        while((p!=NULL)&&(q!=NULL))
        {
            if(p->data<=q->data)
            {
                s=p;
                p=p->next;
            }
            else{
                s=q;
                q=q->next;
            }
            s->next=C.head->next;
            C.head->next=s;
        }//插入c表的头部,即头插法

        if(p==NULL)
        {
            p=q;
        }
        while(p!=NULL)
        {
            s=p;
            p=p->next;
            s->next=C.head->next;
            C.head->next=s;
        }
        //将pq剩余的结点插入到c
        A.head=NULL;
        B.head=NULL;
        //将链表AB的head指针置为空
        //归并的复杂度为O(m+n)
    }

}
void Link::Initiate() {
DeleteAll();
head= NULL;
}
void Link::HeadCreate(int n) {
    //从表尾到表头建立单链表(不带有空白头结点)或者称为 头插法(和顺序表的顺序是倒着的)
    DeleteAll();
    Node *s,*p;
    int i;
    p=NULL;//初始化指针为NULL
    for(i=1;i<=n;i++)
    {
        s = new Node();// new一个对象返回的是一个指针
        cin >> s->data;
        s->next = p;//每次生成新的结点指向上一次生成的新节点,
        //结点生成后使用指针存储位置信息

        p=s; //p指向新建的结点,s指向上一个生成的结点
    }
    head = p;// 最后生成链表的头结点是最后生成的新结点
}
void Link::TrailCreate(int n) {
    //从表尾到表头建立链表(不含有空白头结点)
    DeleteAll();
    Node *s,*p,*r;
    p = NULL;
    for(int i=0;i<n;i++)
    {
        s = new Node();
        cin >> s->data;
        s->next = NULL;
        //新建结点
        if(p=NULL)
            p=r=s; //如果p是NULL,p和s都初始化为第一个节点
        else
        {
            r->next=s;// 按照顺序指向下一个,此时r指向的是新生成结点的上一个结点
            r=s; //尾指针后移,指向当前链表的最后一个结点
        }
    }
    head = p;
}
//没有头结点的话空表和非空表的操作会有差异,因此加入头结点可以将操作统一
void Link::HeadCreateWithHead(int n) {
    //头插法建立单链表 带有空白头结点
    Node *s,*p;
    DeleteAll();
    p = new Node();
    p->next=NULL;
    // 头结点p
    for(int i=1;i<=n;i++)
    {
        s = new Node();
        cin >> s->data;
        s->next = p->next;
        p->next = s;
        //将新的结点插入到头结点p的后面
    }
    head = p;
}
void Link::TrailCreateWithTrail(int n) {
    //带头结点的尾插法
    Node *s, *r,*p;
    DeleteAll();
    p = new Node();
    p->next = NULL;
    //创建头结点
    r = p;
    for (int i = 1; i <=n ; ++i) {
        s = new Node();
        cin >> s->data;
        r->next = s; //让当前链表的最后一个元素指向新生成的结点
        r = s; //队尾指针指向新生成的队尾结点
    }//带头结点的尾插法就是只移动尾指针
    r->next = NULL; //队尾指针下一个指向为空
    head = p;
}
int Link::Length() {
    //求表长,不算进头结点,这里的表长都是算头结点的
    int len= 1;
    Node *p = head->next;
    while (p!=NULL)
    {
        len++;
        p= p->next;
    }
    return --len;
}
//查找操作
Node * Link::Locatei(int i) {
    /*按照序号查找,从链表的第一个元素结点算起,
      判断当前结点是否为第i个,若是,则返回该节点的指针
      否则继续查找,直到表结束为止。若没有第i个结点,则
      返回空;如果i= 0;则返回头指针。
     */
    int j=1;
    if(i== 0) {
        return head;
    }
    Node *p = head ->next;
    while ((p!=NULL)&&(j<i)) //推进指针
    {
        p = p->next;
        j++;
    }
    if(j==i)
        return p;
    else{
        cout << "position is not correct" <<endl;
        return NULL;
    }
}
// 按值查找即定位
Node *Link::Locatex(string data) {
    /* 从链表的第一个元素结点起,判断当前结点值是否等于x,
若是,返回该节点的指针,否则继续下一个结点的查找,直到表尾
 若找不到,则返回空*/
    Node *p;
    p=head->next;
    while(((p!=NULL)&&(p->data!=data)))
        p=p->next;
    if(p)
    {
        return p;
    } else{
        cout << data <<"is not exist!" << endl;
        return NULL;
    }
}
string Link::Get(int i) {
    //读取第i个位置上的元素值
    int j;
    Node *p;
    j=1;
    p = head->next;
    while((j<i)&&(p!=NULL))
    {
        j++;
        p=p->next;
    }
    if((p==NULL)||(j>i))
    {
        cout << "position is not correct!" <<endl;
        return NULL;
    } else
        return p->data;
}
//插入结点,(前插结点)
bool Link::Insert(string data, int i) {
    Node *p,*s;
    p = Locatei(i-1);
    if(p==NULL)
    {
        cout << "position is not correct!" << endl;
        return false;
    }
    s = new Node();
    s->data = data;
    s->next = p->next;
    p->next = s;
    return true;
}
bool Link::Deleted(int i) {
    Node *p = Locatei(i-1);
    Node *q;
    if(p==NULL)
    {
        cout << "position is not correct" << endl;
        return false;
    }
    q= p->next;
    if(q!=NULL)
    {
        p->next = q->next;
        delete q;
        return true;
    }
    else
    {
        cout << "position is not correct!" << endl;
        return false;
    }
}
void Link::Print() {
    Node *p;
    p= head->next;
    while(p!=NULL)
    {
        cout << p->data << " ";
        p= p->next;
    }
    cout << endl;
}
void Link::DeleteAll() {
    Node *p =head,*q;
    while(p!=NULL)
    {
        q=p->next;
        delete p;
        p= q;
    }
    head = NULL;
}
void Link::reverse(Link &H) {
    Node *p,*q;
    p=H.head->next; //p指向第一个数据结点
    H.head->next=NULL; //将原来链表置为空表
    while(p)
    {
        q=p;
        p=p->next;
        q->next=H.head->next;//将当前结点插入到头结点的后面
        H.head->next=q;
        //对链表的数据元素按照顺序扫描一遍,时间复杂度为O(n)
    }
}

int main(){
   
    cout << "hello world" <<endl;
    return 0;
}


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!