数据结构与算法-优先级队列

定义

1)满二叉树:一个高为 h h h的二叉树,如果其节点个数等于 2 h − 1 2^h-1 2h1,则是一个满二叉数。
2)完全二叉树:将满二叉数从根节点开始按层从上到下从左到右编号,如果将满二叉树编号最大的若干个(可以是0个)节点删除的话,形成的新树就是一个完全二叉树
3)大(小)根树:是这样的一颗树,树中每个节点的值都大于(小于)或等于其子节点(如果有子节点的化)的值。注意这里并没有要求是二叉树,可以多任意叉数)
4)大(小)根 堆 堆 :既是大(小)根树,又是完全二叉树。注意这里必须是完全的且是二叉的树。

完全二叉树需要记住的基本知识点:
1)编号为n的节点的父节点的编号为 n/2; 例如3号节点的父节点为 3/2 = 1号节点
2)编号为n的节点左孩子节点编号为 2n,右孩子节点为2n+1。当前前提是n号节点有左右孩子。当2n 等于二叉树所有节点总数时,n号节点有左孩子,当2n 小于 二叉树所有节点总数时,n号节点有右孩子。

大根堆实现代码:max_heap.h

#include <vector>
#include <iostream>
template <typename T>
class MaxHeapT
{
public:
    MaxHeapT(const std::vector<T> &_data);
    T top();
    void pop();
    void push(const T &data);
    size_t size();

    template <typename T1>
    friend std::ostream &operator<<(std::ostream &out, MaxHeapT<T1> &_max_heap);

private:
    void initialize(const std::vector<T> &_data);

    std::vector<T> elements_;
    size_t element_num_ = 0;
};

template <typename T>
MaxHeapT<T>::MaxHeapT(const std::vector<T> &_data) : element_num_(_data.size())
{
    initialize(_data);
}

template <typename T>
void MaxHeapT<T>::initialize(const std::vector<T> &_data)
{
    T a;
    elements_.push_back(a);
    elements_.insert(elements_.end(), _data.begin(), _data.end());

    size_t root_node_index = element_num_ / 2;

    for (; root_node_index > 0; root_node_index--)
    {
        size_t current_node_index = root_node_index;
        T current_node_value = elements_[current_node_index];
        size_t left_child_index = current_node_index * 2; //left_child_index
        while (left_child_index <= element_num_)
        {
            T larger_child_value = elements_.at(left_child_index); //left_child_value
            size_t larger_child_index = left_child_index;

            if (left_child_index < element_num_)
            {
                size_t right_child_index = left_child_index + 1;
                larger_child_index = elements_[left_child_index] >= elements_[right_child_index] ? left_child_index : right_child_index;
                larger_child_value = elements_[larger_child_index];
            }

            if (current_node_value >= larger_child_value)
            {
                break;
            }

            std::swap(elements_[current_node_index], elements_[larger_child_index]);
            current_node_index = larger_child_index;
            left_child_index = current_node_index * 2;
        }
    }
}

template <typename T>
T MaxHeapT<T>::top()
{
    //assert(element_num_ >= 1);
    return elements_[1];
}

template <typename T>
void MaxHeapT<T>::pop()
{
    if (element_num_ == 0)
        return;

    if (element_num_ == 1)
    {
        elements_.pop_back();
        element_num_--;
        return;
    }

    elements_[1] = elements_[element_num_];
    element_num_--;
    elements_.pop_back();

    size_t current_node_index = 1;
    size_t left_child_index = current_node_index * 2;

    while (left_child_index <= element_num_)
    {
        T current_node_value = elements_[current_node_index];

        size_t larger_child_index = left_child_index;
        T larger_child_value = elements_[larger_child_value];

        if (left_child_index < element_num_)
        {
            size_t right_child_index = left_child_index + 1;
            larger_child_index = elements_[left_child_index] >= elements_[right_child_index] ? left_child_index : right_child_index;
            larger_child_value = elements_[larger_child_index];
        }

        if (current_node_value >= larger_child_value)
        {
            break;
        }

        std::swap(elements_[current_node_index], elements_[larger_child_index]);
        current_node_index = larger_child_index;
        left_child_index = current_node_index * 2;
    }
}

template <typename T>
void MaxHeapT<T>::push(const T &data)
{
    elements_.push_back(data);
    element_num_++;

    size_t current_nodex_index = element_num_;
    size_t parent_node_index = current_nodex_index / 2;

    while (parent_node_index > 0)
    {
        if (elements_[current_nodex_index] > elements_[parent_node_index])
        {
            std::swap(elements_[current_nodex_index], elements_[parent_node_index]);
            current_nodex_index = parent_node_index;
            parent_node_index = current_nodex_index / 2;
        }
        else
        {
            break;
        }
    }
}

template <typename T>
size_t MaxHeapT<T>::size()
{
    return element_num_;
}

template <typename T>
std::ostream &operator<<(std::ostream &out, MaxHeapT<T> &_max_heap)
{
    if (_max_heap.element_num_ < 1)
    {
        out << " no element in maxHeap" << std::endl;
    }
    else
    {
        for (size_t i = 1; i <= _max_heap.element_num_; i++)
        {
            out << _max_heap.elements_[i] << " ";
        }
        out << std::endl;
    }

    return out;
}

测试代码: main.cpp

#include <iostream>
#include <vector>
#include "max_heap.h"


int main()
{
    std::vector<double> datas_double = {3.0,4.0,5.0};
    MaxHeapT<double> max_heap_t(datas_double);

    max_heap_t.push(8.0);
    std::cout<<max_heap_t;
    max_heap_t.push(7);
    std::cout<<max_heap_t;
    max_heap_t.pop();
    std::cout<<max_heap_t;
    
    return 0;
}

编译指令:
g++ --std=c++11 main.cpp

运行结果:

8 5 3 4 
8 7 3 4 5 
7 5 3 4

利用小根堆进行排序列表合并:

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class MinHeap{
public:
    MinHeap(vector<ListNode*> &lists);
    ListNode* top();
    void pop();
    void push(ListNode* _node);
    size_t size();

private:
    void initilize(std::vector<ListNode*> &lists);
    std::vector<ListNode*> node_elements_;
    size_t element_num_;
};

MinHeap::MinHeap(vector<ListNode*> &lists)
{
    initilize(lists);
}

void MinHeap::initilize(std::vector<ListNode*> &lists)
{
    node_elements_.emplace_back(static_cast<ListNode*>(nullptr));
    for(auto &node_ptr : lists)
    {
        if(node_ptr != nullptr)
        {
            node_elements_.emplace_back(node_ptr);
        }
    }

    element_num_ = node_elements_.size() - 1;
    
    size_t root_index = element_num_ / 2;
    for(; root_index > 0; root_index--)
    {
        size_t current_node_index = root_index;
        ListNode* current_node_value = node_elements_[current_node_index];
        size_t left_child_index = current_node_index * 2;

        while(left_child_index <= element_num_)
        {
            size_t smaller_node_index = left_child_index;
            ListNode* smaller_node_value = node_elements_[left_child_index];

            if(left_child_index < element_num_)
            {
                size_t right_child_index = left_child_index + 1;

                smaller_node_index = node_elements_[left_child_index]->val <= node_elements_[right_child_index]->val ? 
                left_child_index : right_child_index;

                smaller_node_value = node_elements_[smaller_node_index];
            }

            if(current_node_value->val <= smaller_node_value->val)
            {
                break;
            }

            std::swap(node_elements_[current_node_index],node_elements_[smaller_node_index]);

            current_node_index = smaller_node_index;
            left_child_index = current_node_index * 2;
        }
    }
}

ListNode* MinHeap::top()
{
    if(element_num_ < 1)
        return nullptr;
    return node_elements_[1];
}

void MinHeap::pop()
{
    if(element_num_ < 1)
        return;
    if(element_num_ == 1)
    {
        node_elements_.pop_back();
        element_num_--;
        return;
    }

    node_elements_[1] = node_elements_[element_num_];
    node_elements_.pop_back();
    element_num_--;

    size_t current_node_index = 1;
    size_t left_child_index = current_node_index * 2;
    while(left_child_index <= element_num_)
    {
        size_t smaller_node_index = left_child_index;
        ListNode* smaller_node_value = node_elements_[left_child_index];
        if(left_child_index < element_num_)
        {
            size_t right_child_index = left_child_index + 1;
            smaller_node_index = node_elements_[left_child_index]->val <= node_elements_[right_child_index]->val ?
                left_child_index : right_child_index;
            
        }

        if(node_elements_[current_node_index]->val > node_elements_[smaller_node_index]->val)
        {
            std::swap(node_elements_[current_node_index],node_elements_[smaller_node_index]);
        }
        else
        {
            break;
        }

        current_node_index = smaller_node_index;
        left_child_index = current_node_index * 2;
    }
}

void MinHeap::push(ListNode* _node)
{
    if(_node == nullptr)
        return;
    if(element_num_ == 0)
    {
        node_elements_.emplace_back(_node);
        element_num_++;
        return;
    }

    node_elements_.emplace_back(_node);
    element_num_++;

    size_t current_node_index = element_num_;
    size_t parent_node_index = current_node_index / 2;
    while(parent_node_index > 0)
    {
        if(node_elements_[current_node_index]->val < node_elements_[parent_node_index]->val)
        {
            std::swap(node_elements_[current_node_index],node_elements_[parent_node_index]);
            current_node_index = parent_node_index;
            parent_node_index = current_node_index / 2;
        }
        else
        {
            break;
        }
    }

}

size_t MinHeap::size()
{
    return element_num_;
}
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        
        MinHeap min_heap(lists);

        ListNode* head_node = min_heap.top();
        ListNode* current_node = head_node;

        while(min_heap.size() > 0)
        {
            min_heap.pop();
            if(current_node != nullptr)
                min_heap.push(current_node->next);
            current_node->next = min_heap.top();
            current_node = current_node->next;
            
        }
        
        return head_node;

    }
};

除了用最大堆可以解上面的题,使用最大左高树也可以解

struct BinaryNode
{
    std::pair<size_t,ListNode*> element;
    BinaryNode *left;
    BinaryNode *right;
    BinaryNode(std::pair<size_t,ListNode*> &_element, BinaryNode *_left = nullptr, BinaryNode *_right = nullptr) : element(_element), left(_left), right(_right)
    {
    }
};

class MinHBLT
{
public:
    MinHBLT(vector<ListNode*> &lists);
    MinHBLT();
    void pop();
    void push(ListNode *_element);
    ListNode* top();
    
    size_t size();
    void print_level();
    void print_mid();
    void print_back();

private:
    /*注意:这里的参数需要是指针的引用类型*/
    void merge(BinaryNode *&x, BinaryNode *&y);
    void initialize(vector<ListNode*> &lists);
    void print_mid(BinaryNode *_node);
    void print_back(BinaryNode *_node);

private:
    BinaryNode *root_;
    size_t element_num_;
};


void MinHBLT::merge(BinaryNode *&x, BinaryNode *&y)
{
    if (y == nullptr)
    {
        return;
    }

    if (x == nullptr)
    {
        x = y;
        return;
    }

    if (x->element.second->val > y->element.second->val)
    {
        std::swap(x, y);
    }

    if (x->left == nullptr)
    {
        x->left = y;
        x->right = nullptr;
        x->element.first = 1;
    }
    else
    {
        merge(x->right,y);
        if (x->left->element.first < x->right->element.first)
            std::swap(x->left, x->right);
        
        x->element.first = x->right->element.first + 1;
    }
}


void MinHBLT::pop()
{
    if(root_ != nullptr)
    {
        BinaryNode *x = root_->left;
        BinaryNode *y = root_->right;

        delete root_;

        merge(x, y);

        root_ = x;
        element_num_--;
    }
}


void MinHBLT::push(ListNode* _element)
{
    if(_element != nullptr)
    {
        std::pair<size_t,ListNode*> ele = std::make_pair(1, _element);
        BinaryNode *y = new BinaryNode(ele);
        merge(root_, y);
        element_num_++;
    }
    
}


ListNode* MinHBLT::top()
{
    if(element_num_ < 1)
        return nullptr;
    return root_->element.second;
}


void MinHBLT::initialize(vector<ListNode*> &lists)
{
    std::queue<BinaryNode *> tree_queue;
    for (size_t i = 0; i < lists.size(); i++)
    {
        if(lists[i] != nullptr)
        {
            std::pair<size_t, ListNode*> element = std::make_pair(1, lists[i]);
            tree_queue.push(new BinaryNode(element));
        }
        
    }

    element_num_ = tree_queue.size();

    for (size_t i = 1; i < element_num_; i++)
    {
        BinaryNode *x = tree_queue.front();
        tree_queue.pop();
        BinaryNode *y = tree_queue.front();
        tree_queue.pop();

        merge(x, y);
        tree_queue.push(x);
    }

    root_ = tree_queue.front();
}


MinHBLT::MinHBLT(vector<ListNode*> &lists)
{
    initialize(lists);
}


MinHBLT::MinHBLT()
{
    root_ = nullptr;
    element_num_ = 0;
}


size_t MinHBLT::size()
{
    return element_num_;
}


class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        
        //MinHeap min_heap(lists);
        MinHBLT min_hblt(lists);

        //ListNode* head_node = min_heap.top();
        ListNode* head_node = min_hblt.top();
        ListNode* current_node = head_node;

        //while(min_heap.size() > 0)
        while(min_hblt.size() > 0)
        {
            //min_heap.pop();
            min_hblt.pop();
            if(current_node != nullptr)
                //min_heap.push(current_node->next);
                min_hblt.push(current_node->next);
            //current_node->next = min_heap.top();
            current_node->next = min_hblt.top();
            current_node = current_node->next;
            
        }
        
        return head_node;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
数据结构和算法是计算机科学中非常重要的概念。数据结构是为解决实际问题而设计的,用于存储和组织数据的方式。它可以分为逻辑结构和物理结构。逻辑结构包括集合结构、线性结构、树形结构和图形结构,而物理结构则包括顺序存储和链式存储。 算法则是解决问题的一系列步骤或操作。它具有输入、输出、有穷性、确定性和可行性这五个基本特性。算法是在数据结构上操作的过程,通过对数据结构的操作实现问题的解决。 在C语言中,我们可以使用不同的数据结构和算法来解决问题。例如,队列是一种常用的数据结构,它可以使用链表来实现,其中包括头结点和尾结点。队列可以进行插入和删除操作,通常使用头尾指针来指示队列的状态。循环队列是一种特殊的队列,当队列满时,头指针会指向尾指针的下一个位置,而当队列为空时,头指针和尾指针指向同一个位置。 另一个常用的数据结构是栈,它具有先进后出的特性。栈的应用包括前缀、中缀和后缀表达式的计算。在这些表达式中,运算符的优先级决定了计算的顺序。前缀表达式将运算符放在操作数之前,后缀表达式将运算符放在操作数之后,而中缀表达式则是我们日常生活中最常见的形式。 综上所述,数据结构和算法是C语言中解决问题的重要工具。我们可以根据问题的特点选择合适的数据结构和算法来实现解决方案。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [数据结构和算法(C语言)](https://blog.csdn.net/weixin_60096751/article/details/123643490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [C语言数据结构与算法](https://blog.csdn.net/Syext/article/details/129896715)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值