当前位置: 代码网 > it编程>软件设计>算法 > 【贪心算法】贪心算法原理思想、算法步骤,应用示例(找零问题、活动选择问、霍夫曼编码、最小生成树问题、车辆路径问题)

【贪心算法】贪心算法原理思想、算法步骤,应用示例(找零问题、活动选择问、霍夫曼编码、最小生成树问题、车辆路径问题)

2024年07月28日 算法 我要评论
贪心算法是一种基于贪心策略的优化算法,它在每一步选择中都采取当前状态下的最优决策,而不考虑未来的后果。通常,这种算法对于解决一些最优化问题非常有效,尤其是那些可以通过局部最优解来达到全局最优解的问题。

        贪心算法是一种基于贪心策略的优化算法,它在每一步选择中都采取当前状态下的最优决策,而不考虑未来的后果。通常,这种算法对于解决一些最优化问题非常有效,尤其是那些可以通过局部最优解来达到全局最优解的问题。

1 贪心算法的基本思想:

2 示例:找零问题

问题描述: 给定一些面额不同的硬币,如1元、5元、10元,要找零n元,找零的硬币数量要尽可能少。

贪心策略: 在每一步选择中,选择面额最大的硬币,直到找零的总金额达到n。

算法步骤:

  1. 初始化一个空列表,用于存储找零的硬币。
  2. 从面额最大的硬币开始,将尽可能多的这个硬币加入列表,直到总金额超过n。
  3. 如果总金额等于n,算法结束。否则,将面额减小到次大的硬币,重复步骤2。

python 代码示例:

def greedy_change(n, coins):
    coins.sort(reverse=true)  # 按面额降序排列
    change = []  # 存储找零的硬币
    total = 0  # 当前找零的总金额

    for coin in coins:
        while total + coin <= n:
            change.append(coin)
            total += coin

    return change

# 示例
n = 63
coin_denominations = [1, 5, 10, 20, 50]
result = greedy_change(n, coin_denominations)
print("greedy change for", n, ":", result)

在这个例子中,贪心算法首先选择面额最大的硬币(50元),然后选择10元,最后选择3个1元,完成找零过程。尽管这个算法可能无法得到最优解,但它通常能够得到一个近似最优解,而且计算效率高。

3 示例: 活动选择问题(activity selection problem):

  • 问题描述: 给定一系列活动,每个活动都有开始时间和结束时间,目标是选择尽可能多的互不相交的活动。
  • 贪心策略: 在每一步选择中,选择结束时间最早的活动,以便腾出更多时间给其他活动。
  • 应用场景: 会议室安排、课程表安排等。
  • python 代码示例:
  • def activity_selection(activities):
        # 按照结束时间排序
        sorted_activities = sorted(activities, key=lambda x: x[1])
        selected_activities = [sorted_activities[0]]  # 选择第一个活动
        last_end_time = sorted_activities[0][1]
    
        # 选择互不相交的活动
        for activity in sorted_activities[1:]:
            if activity[0] >= last_end_time:
                selected_activities.append(activity)
                last_end_time = activity[1]
    
        return selected_activities
    
    # 示例
    activities = [(1, 4), (3, 5), (0, 6), (5, 7), (3, 9), (5, 9), (6, 10), (8, 11), (8, 12), (2, 14), (12, 16)]
    result = activity_selection(activities)
    print("selected activities:", result)
    

4 示例:霍夫曼编码(huffman coding):

  • 问题描述: 给定一组字符及其出现的频率,构建一个最优的二进制编码,使得出现频率高的字符具有较短的编码。
  • 贪心策略: 构建霍夫曼树,选择出现频率最低的两个节点合并,重复此过程直到只剩一个节点。
  • 应用场景: 数据压缩、图像编码等。
  • python 代码示例:
  • import heapq
    from collections import defaultdict
    
    # 定义霍夫曼树的节点类
    class huffmannode:
        def __init__(self, char, freq):
            self.char = char
            self.freq = freq
            self.left = none
            self.right = none
    
        def __lt__(self, other):
            return self.freq < other.freq
    
    # 构建霍夫曼树
    def build_huffman_tree(freq_map):
        # 利用最小堆来实现构建霍夫曼树的过程
        min_heap = [huffmannode(char, freq) for char, freq in freq_map.items()]
        heapq.heapify(min_heap)
    
        while len(min_heap) > 1:
            left = heapq.heappop(min_heap)
            right = heapq.heappop(min_heap)
            merged = huffmannode(none, left.freq + right.freq)
            merged.left = left
            merged.right = right
            heapq.heappush(min_heap, merged)
    
        return min_heap[0]
    
    # 生成霍夫曼编码
    def generate_huffman_codes(root, current_code, codes):
        if root is not none:
            if root.char is not none:
                codes[root.char] = current_code
            generate_huffman_codes(root.left, current_code + '0', codes)
            generate_huffman_codes(root.right, current_code + '1', codes)
    
    # 霍夫曼编码
    def huffman_coding(text):
        freq_map = defaultdict(int)
        for char in text:
            freq_map[char] += 1
    
        root = build_huffman_tree(freq_map)
        codes = {}
        generate_huffman_codes(root, '', codes)
    
        # 将原始文本编码为霍夫曼编码
        encoded_text = ''.join(codes[char] for char in text)
        return encoded_text, codes
    
    # 示例
    text_to_encode = "huffman coding is fun!"
    encoded_text, huffman_codes = huffman_coding(text_to_encode)
    
    # 打印结果
    print("original text:", text_to_encode)
    print("encoded text:", encoded_text)
    print("huffman codes:", huffman_codes)
    

5  示例:最小生成树问题(minimum spanning tree):

  • 问题描述: 给定一个连通的无向图,找到一个最小权重的树,使得图中所有节点都连接在一起。
  • 贪心策略: 使用kruskal算法或prim算法,每次选择边权重最小的边加入生成树。
  • 应用场景: 网络设计、电缆布线等。
  • python 代码示例:
    • import heapq
      
      def prim(graph):
          n = len(graph)
          visited = [false] * n
          min_heap = [(0, 0)]  # (权重, 节点)的最小堆
          minimum_spanning_tree = []
      
          while min_heap:
              weight, node = heapq.heappop(min_heap)
              if not visited[node]:
                  visited[node] = true
                  minimum_spanning_tree.append((weight, node))
      
                  for neighbor, edge_weight in graph[node]:
                      heapq.heappush(min_heap, (edge_weight, neighbor))
      
          return minimum_spanning_tree
      
      # 示例
      graph = {
          0: [(1, 2), (3, 1)],
          1: [(0, 2), (3, 3), (2, 1)],
          2: [(1, 1), (3, 5)],
          3: [(0, 1), (1, 3), (2, 5)]
      }
      
      result = prim(graph)
      print("minimum spanning tree:", result)
      

6 示例:车辆路径问题(vehicle routing problem):

  • 问题描述: 有一组客户点和一个中心仓库,目标是找到一条路径,使得所有客户都被访问,并且路径总长度最短。
  • 贪心策略: 从仓库出发,选择离当前位置最近的客户点,重复此过程直到所有客户都被访问。
  • 应用场景: 物流配送、快递路线规划等。
  • python 代码示例:
  • import numpy as np
    
    def euclidean_distance(point1, point2):
        # 计算两点之间的欧几里德距离
        return np.linalg.norm(np.array(point1) - np.array(point2))
    
    def vehicle_routing(customers, warehouse):
        route = [warehouse]  # 路线的起始点是仓库
        remaining_customers = set(customers)
    
        while remaining_customers:
            # 计算当前位置到所有剩余客户点的距离,并选择最近的客户点
            current_location = route[-1]
            nearest_customer = min(remaining_customers, key=lambda customer: euclidean_distance(current_location, customer))
            
            # 将最近的客户点添加到路线中
            route.append(nearest_customer)
            remaining_customers.remove(nearest_customer)
    
        # 返回最终路线
        return route
    
    # 示例
    warehouse_location = (0, 0)
    customer_locations = [(1, 2), (3, 5), (6, 8), (9, 4), (7, 1)]
    
    final_route = vehicle_routing(customer_locations, warehouse_location)
    
    # 打印结果
    print("warehouse location:", warehouse_location)
    print("customer locations:", customer_locations)
    print("final route:", final_route)
    
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com