[数据结构和算法]C/C++双向循环链表实现(增删改查排序)

之前也写过一篇C语言实现简单的双向循环链表,现在使用C++再来扩展一下内容。除了节点的插入、删除,还增加了一些链表的其他操作,包括节点修改、节点替换、节点查找、值查找、值排序等等。内容还是挺丰富的,废话不多说,上代码吧,有问题的欢迎提出来

定义数据结构

顺便,一些简单的函数就在类中实现了

class node{
    public:
        node *prev;
        node *next;
        uint32_t data;
};

typedef class node Node,*pNode;
class list:public node{
    public:
        list(){ 	//构造一个链表头
            head = new Node;
            list_len = 0;
            head->prev = head;
            head->next = head;
            list_len++;
            cout << "list Head:" << head << endl;  
        }
        ~list(){
            head = NULL;
            delete head;
        }

        //add and delete
        pNode list_addhead(uint32_t dat);	//头插
        pNode list_addtail(uint32_t dat);		//尾插
        pNode list_add(uint16_t coord, uint32_t dat);	//按位置插入
        pNode list_delhead(void);	//头删
        pNode list_deltail(void);	//尾删
        pNode list_del(uint16_t coord);	//按位置删除
        pNode list_delnode(pNode node);	//按节点地址删除

        //find and change
        pNode list_sortval(void);	//值排序,交换值,不改变节点
        pNode list_sortnode(void);	//值排序,直接交换节点
        pNode list_findval(uint32_t dat);   //值查找
        uint32_t list_findcursor(uint16_t cnt);	//位置查找
        pNode list_changeval(uint32_t src_dat, uint32_t des_dat){	//修改值
            pNode tmp = NULL;
            tmp = list_findval(src_dat);
            if(tmp != head){    //find  effective value
                tmp->data = des_dat;
            }
            return head;
        }
        pNode list_changecursorval(uint16_t cnt, uint32_t des_dat){	//修改特定位置的值
            if(cnt >= get_list_len()){
                cout << "param error!!!" << endl;
                return 0;
            }
            pNode tmp = head;
            while(cnt--){
                tmp = tmp->next;
            }
            tmp->data = des_dat;
            return head;
        }
        pNode list_getnode(uint16_t cnt){	//获取节点位置
            if(cnt == 0 || cnt >= get_list_len()){
                cout << "param error!!!" << endl;
                return 0;
            }
            cout << "cnt: " << cnt <<"\t";
            pNode tmp = head;
            while(cnt--){
                tmp = tmp->next;
            }
            return tmp;
        }
        pNode list_changenode(pNode src_node, pNode des_node);	//交换节点
        uint32_t get_list_len(void){	//获取链表长度
            return list_len;
        }

        pNode list_clear(void){	//清除链表
            pNode cursor = head->next;
            while(cursor != head){
                head->next = cursor->next;
                cursor->next->prev = head;
                list_len--;
                cursor = cursor->next;
                delete(cursor);
            }
            return head;
        }

        void list_print(void){	//链表打印
            if(NULL == head){
                cout << "head point empty!!!" << endl;
                return;
            }
            if(head == head->next){
                cout << "List empty" << endl;
                return;
            }
            pNode tmp = head->next;
            while(tmp != head){
                cout << "P:" << tmp << "\tData:" << tmp->data+0 << endl;
                tmp = tmp->next;
            }
        }
    protected:
    private:
        pNode head = NULL;	
        uint16_t list_len;
};
链表的插入
pNode list::list_addhead(uint32_t dat){
    if(NULL == head)    list();
    pNode tmp = new Node;
    if(tmp == head) tmp = new Node;
    list_len++;
    tmp->next = head->next;
    tmp->prev = head;
    head->next->prev = tmp;
    head->next = tmp;
    tmp->data = dat;
    return head;
}

pNode list::list_addtail(uint32_t dat){
    if(NULL == head)    list();
    pNode tmp = new Node;
    list_len++;
    tmp->prev = head->prev;
    tmp->next = head;
    head->prev->next = tmp;
    head->prev = tmp;
    tmp->data = dat;
    return head;
}

pNode list::list_add(uint16_t coord, uint32_t dat){
    if(NULL == head)    list();
    pNode tmp = new Node;
    pNode cursor = head->next;
    list_len++;
    while(coord--){
        cursor = cursor->next;
    }
    tmp->prev = cursor->prev;
    tmp->next = cursor;
    cursor->prev->next = tmp;
    cursor->prev = tmp;
    tmp->data = dat;
    return head;
}
链表的删除
pNode list::list_delhead(void){
    if((NULL==head) || (head->next==head)){
        cout << "List is empty" << endl;
        return head;
    }
    pNode tmp = head->next;
    head->next = tmp->next;
    tmp->next->prev = head;
    list_len--;
    delete tmp;
}
pNode list::list_deltail(void){
    if((NULL==head) || (head->next==head)){
        cout << "List is empty" << endl;
        return head;
    }
    pNode tmp = head->prev;
    head->prev = tmp->prev;
    tmp->prev->next = head;
    list_len--;
    delete tmp;
}
pNode list::list_del(uint16_t coord){
    if((NULL==head) || (head->next==head)){
        cout << "List is empty" << endl;
        return head;
    }
    if(coord >= get_list_len()){
        cout << "param error!!!" << endl;
        return head;
    }
    pNode cursor = head->next;
    pNode tmp = NULL;
    while(coord--){
        cursor = cursor->next;
    }
    tmp = cursor;
    cursor->prev->next = cursor->next;
    cursor->next->prev = cursor->prev;
    list_len--;
    delete cursor;
}
pNode list::list_delnode(pNode node){
    pNode tmp = head->next;
    while(tmp != head){
        if(node == tmp){
            node->prev->next = node->next;
            node->next->prev = node->prev;
            list_len--;
            delete node;
            cout << "delete Node success" << endl;
            return head;
        }
        tmp = tmp->next;
    }
    cout << "Not find this Node" << endl;
    return head;
}
链表的查找

链表的值查找:检索链表是是否有该值,有的话返回该节点的位置;
链表的位置查找:查找链表的第n个节点的值是多少,并返回该值;

pNode list::list_findval(uint32_t dat){
    pNode tmp = head->next;
    while(tmp != head){
        if(dat == tmp->data){
            cout << "find dat:" << dat << "\taddr:" << tmp << endl;
            return tmp;
        }
        tmp = tmp->next;
    }
    cout << "Not find dat" << endl;
    return head;
}

uint32_t list::list_findcursor(uint16_t cnt){
    if(cnt >= get_list_len()){
        cout << "param error!!!" << endl;
        return 0;
    }
    pNode tmp = head;
    while(cnt--){
        tmp = tmp->next;
    }
    return tmp->data;
}
链表的节点替换

先判断替换的两个节点是否在该链表中,是否为同一个节点;
判断两个节点是否相邻;
节点处理咯

pNode list::list_changenode(pNode src_node, pNode des_node){
    pNode tmp = head->next;
    uint8_t flag = 0;
    cout << "\n\nsrc_node:" << src_node << "\tdes_node:" << des_node << endl;
    if(src_node == des_node){
        cout << "desNode equel desNode" << endl;
        return head;
    }
    while(tmp != head){
        if((tmp==src_node) || (tmp==des_node)){
            flag++;
        }
        tmp = tmp->next;
    }
    if(2 != flag){
        cout << "pNode param error" << endl;
        return head;
    }
    if(src_node->next == des_node){
        src_node->prev->next = src_node->next;
        src_node->next->prev = src_node->prev;

        src_node->next = des_node->next;
        src_node->prev = des_node;
        des_node->next->prev = src_node;
        des_node->next = src_node;
    }else if(des_node->next == src_node){
        des_node->prev->next = des_node->next;
        des_node->next->prev = des_node->prev;

        des_node->next = src_node->next;
        des_node->prev = src_node;
        src_node->next->prev = des_node;
        src_node->next = des_node;
    }else{
        pNode pSrc = src_node->prev;
        pNode pDes = des_node->prev;
        src_node->prev->next = src_node->next;
        src_node->next->prev = src_node->prev;

        src_node->next = pDes->next;
        src_node->prev = pDes;
        pDes->next->prev = src_node;
        pDes->next = src_node;

        des_node->prev->next = des_node->next;
        des_node->next->prev = des_node->prev;

        des_node->next = pSrc->next;
        des_node->prev = pSrc;
        pSrc->next->prev = des_node;
        pSrc->next = des_node;
    }
    return head;
}
链表的排序

一、根据链表中的数据进行升序排序,只交换值,节点不做更改;
二、根据链表中的数据进行升序排序,直接交换节点的位置。

pNode list::list_sortval(void){
    uint16_t len = get_list_len();
    for(uint16_t i=0;i<len-1;i++){
        for(uint16_t j=0;j<len-i-1;j++){
            if(list_findcursor(j) > list_findcursor(j+1)){
                uint32_t tmp = list_findcursor(j+1);
                list_changecursorval(j+1, list_findcursor(j));
                list_changecursorval(j, tmp);
            }
        }
    }
    return head;
}
pNode list::list_sortnode(void){
    uint16_t len = get_list_len();
    for(uint16_t i=0;i<len-1;i++){
        for(uint16_t j=0;j<len-i-1;j++){
            if(list_findcursor(j) > list_findcursor(j+1)){
                list_changenode(list_getnode(j), list_getnode(j+1));
            }
        }
    }
    return head;
}

该链表的功能函数较多,整体测试篇幅有限,所以进行功能性分块测试,有兴趣的也可以自行综合测试。

1.插入测试
int main(void){
    list L;
    uint16_t cnt = 0;
    uint16_t cursor = 0;
    uint32_t tmp = 0;
    cout << "Insert Node from head" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();

    cout << "\nInsert Node from tail" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addtail(tmp);
    }
    L.list_print();
    L.get_list_len();
}

在这里插入图片描述

2. 删除测试
int main(void){
    list L;
    uint16_t cnt = 0;
    uint16_t cursor = 0;
    uint32_t tmp = 0;
    cout << "Insert Node from head" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();
    
    cout << "\ndelete Node from head" << endl;
    cout << "How many Node need to delete" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        L.list_delhead();
    }
    L.list_print();
    L.get_list_len();

    cout << "\ndelete Node from tail" << endl;
    cout << "How many Node need to delete" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        L.list_deltail();
    }
    L.list_print();
    L.get_list_len();

    cout << "\ndelete Node from anywhere" << endl;
    cout << "How many Node need to delete" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> cursor;
        L.list_del(cursor);
    }
    L.list_print();
    L.get_list_len();
}

在这里插入图片描述

3.查找测试
int main(void){
    list L;
    uint16_t cnt = 0;
    uint16_t cursor = 0;
    uint32_t tmp = 0;
    cout << "Insert Node from head" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();

    cout << "\nfind function test" << "\nEnter the value to look for" << endl;
    cin >> tmp;
    L.list_findval(tmp);
    cin >> tmp;
    L.list_findval(tmp);

    cout << "\nEnter the cursor to look for" << endl;
    cin >> tmp;
    cout << "Get value:" << L.list_findcursor(tmp) << endl;
    cin >> tmp;
    cout << "Get value:" << L.list_findcursor(tmp) << endl;

    cout << "\nGet Node" << endl;
    cin >> cursor;
    L.list_getnode(cursor);
    cin >> cursor;
    L.list_getnode(cursor);
}

在这里插入图片描述

4.修改测试
int main(void){
    list L;
    uint16_t cnt = 0;
    uint16_t cursor = 0;
    uint32_t tmp = 0;
    uint32_t val = 0;
    cout << "Insert Node from head" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();

    cout << "\nchange function test" << "\nEnter the value to replace" << endl;
    cin >> tmp >> val;
    L.list_changeval(tmp, val);
    L.list_print();
    cin >> tmp >> val;
    L.list_changeval(tmp, val);
    L.list_print();

    cout << "\nEnter the value and coord to replace" << endl;
    cin >> cursor >> tmp;
    L.list_changecursorval(cursor, tmp);
    L.list_print();
    cin >> cursor >> tmp;
    L.list_changecursorval(cursor, tmp);
    L.list_print();

    cout << "\nChange Node" << endl;
    cin >> cnt >> cursor;
    L.list_changenode(L.list_getnode(cnt), L.list_getnode(cursor));
    L.list_print();
    cin >> cnt >> cursor;
    L.list_changenode(L.list_getnode(cnt), L.list_getnode(cursor));
    L.list_print();
}

把值进行替换
在这里插入图片描述
将第n个节点的值进行替换
在这里插入图片描述
将两个节点进行替换,包括节点的地址
在这里插入图片描述

5.链表排序测试
int main(void){
    list L;
    uint16_t cnt = 0;
    uint16_t cursor = 0;
    uint32_t tmp = 0;
    uint32_t val = 0;
    cout << "Insert Node from head" << endl;
    cout << "How many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();

    cout << "\nSort the list, Just sort value" << endl;
    L.list_sortval();
    L.list_print();

    L.list_clear();

    cout << "\nHow many Node need to insert" << endl;
    cin >> cnt;
    for(uint16_t i=0;i<cnt;i++){
        cin >> tmp;
        L.list_addhead(tmp);
    }
    L.list_print();
    L.get_list_len();
    cout << "\nSort the list" << endl;
    L.list_sortnode();
    L.list_print();
}

在这里插入图片描述

链表的增删改查排序等操作就完了
结合例程,大家可以试着用链表实现栈、队列、环形缓冲区、拆分链表、接合链表、链表的多种排序、判断链表是否有环、哈希链表等更复杂的数据结构和算法咯

6.综合测试

== 略 略略略==

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值