C++ 模板级实现单链表

数据结构老师老教授了,写的单链表模板很厉害,不同于网上大多数链表基于C语言实现,涉及到C++部分的就cin cout。照着老师给的模板实现了C++的单链表。算是把C++的特性用得出神入化了。

设计非递减有序的带头结点的单链表LinkList。编写程序,实现从LinkList中删除值相同的多余结点。

  • 需求分析:包含题目要求,程序功能,运行方式,测试数据等

       题目要求设计非递减有序单链表。

单链表要求实现删除有相同值的结点,让单链表结点中每个结点值不相同。通过运行程序,选择删除相同值后,对相同的值进行删除。通过输入不同值,有些值只输入一次,而部分值重复输入,程序对输入值时能否做到正确删除来判断程序能否正确运行。

先给关键代码,再给完整代码

单链表:

设置单链表结点结构,数据域data和指针域next,并编写相应的get和set函数。

class LNode{//单链表结点结构
    private:
        float data;//数据域
        LNode <float> *next;//指针域
}

 再设置单链表存储结构,头指针,并初始化。

class LinkList{//带头结点单链表存储结构
    private:
        LNode <float> *front;//头指针
    public:
        LinkList(){//初始化
            front = new LNode <float>;
        }
        ~LinkList(){
            DestroyList();
        }

 删除相同值:创建后继指针,q指针和r指针指向头指针,*p指向头结点后一位,当p不为空时,循环赋值,从第一位依次对比后面数字,出现相同时,r后移,q的下一个结点赋值为r的下下个结点,即跳过相同数据结点。不相同时,继续循环,然后依次对比。第一个数据对比完成,且跳过相同数据,再从第二个非相同数据继续按上面方法对比。

void deleteSameNumber(){//删除相同值
            LNode <float> *p = front ->getNext();//*p指向头结点后一位
            LNode <float> *q = front;
            LNode <float> *r = front;
            while (p != NULL) {//当p不为空时,继续循环,从第一位依次对比后面数字
                q = p;
                while (q->getNext()!=NULL) {//当q不为空时,继续循环,从第一位依次对比后面数字
                    if(p->getData() == q->getNext()->getData()){//出现相同时
                        r = q->getNext();
                        q->setNext(r->getNext());//q的下一个结点为r的下下个结点,跳过相同数据结点。
                        delete r;//释放
                    }else {
                        q = q->getNext();//不相同时,继续循环。
                    }
                }
                p = p->getNext();//指向下一个结点,下一位结点的数字继续对比。
            }
        }

非递减排序:对链表中的值进行判断,创建两个指针,一个指针指向头结点,一个作为后继指针,当后继指针的值大于前面指针的值时,指针向后,后结点小于前结点时候交换,s链表存储p,直到后继指针结束,然后第一个指针后移,后继指针指向第一个指针后面,循环前面的步骤直至排序完成。

void sortNumber(){//非递减排序
            LNode <float> *p,*s;
            if(front->getNext()!=NULL){//链表非空时
                LNode <float> *pre = front;//头指针
                LNode <float> *q = front->getNext();//头指针后结点
                if(q->getNext() != NULL){
                    p = q->getNext();//p为q后继
                    while (p != NULL){//p非空时
                        while (p->getData()>=q->getData()){//后结点大于前结点时
                            p = p->getNext();//依次向后
                            q = q->getNext();
                        }
                        if(p!=NULL&&p->getData()<q->getData()){//后结点小于前结点时候(此时交换)
                            s = p;//存储p
                            q->setNext(p->getNext());//q后继为p的后继
                            p = p->getNext();//p后移
                            while (s->getData()>pre->getNext()->getData()) {//当s大于头指针时
                                pre = pre->getNext();//头指针指向第二位
                            }
                            s->setNext(pre->getNext());//否则s换为头指针后一位
                            pre->setNext(s);//头指针赋值为s(交换)
                            pre = front;//pre重新指向头结点
                        }
                    }
                }

完整代码

#include <iostream>
#include <stdlib.h>
using namespace std;

template<class E>
class LNode{//单链表结点结构
    private:
        float data;//数据域
        LNode <float> *next;//指针域
    public:
        LNode(){
            next = NULL;
        }

        LNode(float data,LNode <float> *next = NULL){
            this->data = data;
            this->next = next;
        }

        float getData() const{
            return data;
        }

        LNode <float>* getNext() const{
            return next;
        }

        void setData(float data){
            this->data = data;
        }

        void setNext(LNode <float> *next){
            this->next = next;
        }
};

template<class E>
class LinkList{//带头结点单链表存储结构
    private:
        LNode <float> *front;//头指针
    public:
        LinkList(){//初始化
            front = new LNode <float>;
        }

        ~LinkList(){
            DestroyList();
        }

        void DestroyList(){//销毁单链表
            LNode<float> *p;
            while (front != NULL) {
                p = front;
                front = front->getNext();
                delete p;
            }
        }

        void ClearList(){//清空单链表
            if(front == NULL){
                front = new LNode<float>;
                return;
            }
            LNode <float> *p = front ->getNext();
            front -> setNext(NULL);
            while (p != NULL) {
                LNode <float> *q = p;
                p = p->getNext();
                delete q;
            }
        }

        bool ListEmpty(){//判断表空
            return front->getNext();
        }

        int ListLength(){//求链表长度
            int k = 0;
            LNode <float> *p = front ->getNext();
            while(p != NULL){
                k++;
                p = p->getNext();
            }
            return k;
        }

        float GetElem(int i){//返回链表中第i个元素的值
            LNode <float> *p = front->getNext();//初始化
            int j = 1;//计数器
            while (p&&j<i) {
                p = p->getNext();//指向下一个结点
                j++;
            }
            if(!p||j>i)
                exit(1);
            return p->getData();
        }

        LNode <float> *LocateElem(float e){//查找
            LNode <float> *p = front->getNext();//初始化
            while(p != NULL){//向后扫描,知道p空
                if(p->getData() == e)
                    return p;//查找成功返回p
                p = p->getNext();//指向下一个结点
            }
            return p;//查找失败返回NULL
        }

        bool ListInsert(int i,float e){//在第i个位置插入值为e的结点
            LNode <float> *p = front;//初始化
            int j = 0;
            while (p&&j<i-1) {
                p = p->getNext();
                j++;
            }//查找i-1个结点,p指向该结点
            if(!p||j>i-1)
                return false;
            p->setNext(new LNode <float>(e,p->getNext()));//结点*p的指针域指向生成新结点
            return true;
        }

        bool ListDelete(int i){//删除第i个元素
            LNode <float> *p = front;//初始化
            int j = 0;
            while (p&&j<i-1) {
                p = p->getNext();
                j++;
            }//查找第i个结点
            if(!(p->getNext())||j>i-1)
                return false;
            LNode <float> *q = p->getNext();//临时保存以备释放
            p->setNext(q->getNext());//改变删除结点前驱结点指针域
            delete q;//释放
            return true;
        }

        void CreateList_H(float a[],int n){//前插法创建单链表
            this ->ClearList();
            LNode<float> *p;
            for(int i = 0;i<n;i++){
                p = new LNode <float>(a[i],front->getNext());//生成新结点p
                front ->setNext(p);//新结点*p插入到头结点之后
            }
        }

        void CreateList_R(float a[],int n){//后插法创建单链表
            this->ClearList();
            LNode <float> *p,*r;//r指向最后结点
            r = front;//尾指针指向头结点
            for(int i = 0;i<n;i++){
                p = new LNode <float>(a[i]);//生成新结点*p
                r->setNext(p);//新结点*p插入尾结点*r之后
                r = p;//r指向新尾结点p
            }
        }

        void print(){
            LNode <float> *node = front->getNext();
            while (node != NULL) {
                cout<<"(";
                cout<< node->getData()<<"";
                node = node->getNext();
                cout<<")";
            }

        }

        void sortNumber(){//非递减排序
            LNode <float> *p,*s;
            if(front->getNext()!=NULL){//链表非空时
                LNode <float> *pre = front;//头指针
                LNode <float> *q = front->getNext();//头指针后结点
                if(q->getNext() != NULL){
                    p = q->getNext();//p为q后继
                    while (p != NULL){//p非空时
                        while (p->getData()>=q->getData()){//后结点大于前结点时
                            p = p->getNext();//依次向后
                            q = q->getNext();
                        }
                        if(p!=NULL&&p->getData()<q->getData()){//后结点小于前结点时候(此时交换)
                            s = p;//存储p
                            q->setNext(p->getNext());//q后继为p的后继
                            p = p->getNext();//p后移
                            while (s->getData()>pre->getNext()->getData()) {//当s大于头指针时
                                pre = pre->getNext();//头指针指向第二位
                            }
                            s->setNext(pre->getNext());//否则s换为头指针后一位
                            pre->setNext(s);//头指针赋值为s(交换)
                            pre = front;//pre重新指向头结点
                        }
                    }
                }
            }
        }

        void sortNumberInsert(float e){//插入排序
            LNode <float> *q = front;//头指针
            LNode <float> *p;
            for(int i = 0; q->getData()<=e && q != NULL;i++){
                p = q;//前驱
                q = q->getNext();
            }
            p->setNext(new LNode <float>(e,p->getNext()));//创建结点赋值
        }

        void userGuide(){//用户指引
            cout<<"输入1,创建链表。"<<endl;
            cout<<"输入2,清空链表。"<<endl;
            cout<<"输入3,插入数据。"<<endl;
            cout<<"输入4,删除指定位置数据。"<<endl;
            cout<<"输入5,查找指定位置数据。"<<endl;
            cout<<"输入6,打印链表。"<<endl;
            cout<<"输入7,删除相同的数字。"<<endl;
        }

        void deleteSameNumber(){//删除相同值
            LNode <float> *p = front ->getNext();//*p指向头结点后一位
            LNode <float> *q = front;
            LNode <float> *r = front;
            while (p != NULL) {//当p不为空时,继续循环,从第一位依次对比后面数字
                q = p;
                while (q->getNext()!=NULL) {//当q不为空时,继续循环,从第一位依次对比后面数字
                    if(p->getData() == q->getNext()->getData()){//出现相同时
                        r = q->getNext();
                        q->setNext(r->getNext());//q的下一个结点为r的下下个结点,跳过相同数据结点。
                        delete r;//释放
                    }else {
                        q = q->getNext();//不相同时,继续循环。
                    }
                }
                p = p->getNext();//指向下一个结点,下一位结点的数字继续对比。
            }
        }
};

int main()
{
    LinkList <float> LinkList;
    int n, type,t;
    float num;
    do{
        LinkList.userGuide();
        cin>>type;
        switch (type) {
            case 1:{
            cout<<"输入链表的数据个数:";cin>>n;
            float a[n];
            for(int i = 0;i<n;i++){
                cout<<"输入数据("<<i+1<<"):";cin>>a[i];
            }
            LinkList.CreateList_R(a, n);
            LinkList.sortNumber();
            LinkList.print();
            break;}
            case 2:
            LinkList.ClearList();
            break;
            case 3:
            cout<<"输入数据:";
            cin>>num;
            LinkList.sortNumberInsert(num);
            break;
            case 4:
            int position1;
            cout<<"输入删除的位置:";
            cin>>position1;
            LinkList.ListDelete(position1);
            break;
            case 5:
            int position2;
            cout<<"输入查找的位置:";
            cin>>position2;
            cout<<"数据为:"<<LinkList.GetElem(position2);
            break;
            case 6:
            LinkList.print();
            break;
            case 7:
            LinkList.print();
            cout<<endl;
            cout<<"以上为删除前"<<endl;
            cout<<"以下为删除后"<<endl;
            LinkList.deleteSameNumber();
            LinkList.print();
            break;
        }
        cout<<"如需进行其他操作,请输入1:";
        cin>>t;
    }while(t == 1);
    return 0;
}

 测试结果

 以上为数据只有两个重复时候的删除,可见删除成功,且数据排序成功。

 以上为当数据有相同且相同的数据值各不相同时的删除,可见删除成功,且数据排序成功。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
以下是清空带头结点单链表的C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 typedef struct ListNode { int val; // 节点的值 struct ListNode *next; // 指向下一个节点的指针 } ListNode; // 定义带头结点单链表结构体 typedef struct LinkedList { ListNode *head; // 指向头结点的指针 int size; // 链表大小 } LinkedList; // 初始化链表 LinkedList *initLinkedList() { LinkedList *list = (LinkedList *)malloc(sizeof(LinkedList)); ListNode *head = (ListNode *)malloc(sizeof(ListNode)); head->val = 0; head->next = NULL; list->head = head; list->size = 0; return list; } // 清空链表 void clearLinkedList(LinkedList *list) { if (list == NULL) return; ListNode *p = list->head->next; while (p != NULL) { ListNode *tmp = p; p = p->next; free(tmp); } list->head->next = NULL; list->size = 0; } // 主函数 int main() { // 初始化链表 LinkedList *list = initLinkedList(); // 在链表中添加节点 ListNode *node1 = (ListNode *)malloc(sizeof(ListNode)); node1->val = 1; node1->next = NULL; list->head->next = node1; list->size++; ListNode *node2 = (ListNode *)malloc(sizeof(ListNode)); node2->val = 2; node2->next = NULL; node1->next = node2; list->size++; // 清空链表 clearLinkedList(list); // 输出链表大小 printf("链表大小为:%d\n", list->size); // 链表大小为:0 return 0; } ``` 以上代码中,首先我们定义了链表节点的结构体 `ListNode` 和带头结点单链表的结构体 `LinkedList`。在 `initLinkedList` 函数中,我们首先动态分配了一个 `LinkedList` 类型的内存空间和一个 `ListNode` 类型的内存空间,并将头结点的值设为0,指向NULL。接着,我们将 `list->head` 指向头结点,并将链表大小初始化为0。在 `clearLinkedList` 函数中,我们首先检查链表是否为空,然后使用指针 `p` 遍历链表中的每个节点。对于每个节点,我们先使用指针 `tmp` 保存该节点的地址,然后将 `p` 指向下一个节点,并释放 `tmp` 所指向的内存空间。最后,我们将 `list->head->next` 指向NULL,并将链表大小设置为0。 在主函数中,我们首先初始化链表,然后在链表中添加了两个节点。接着,我们调用 `clearLinkedList` 函数清空链表,并输出链表的大小。注意,由于我们在 `clearLinkedList` 函数中将链表大小设置为0

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kun.A.A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值