-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrestaurant.py
More file actions
157 lines (121 loc) · 4.76 KB
/
Copy pathrestaurant.py
File metadata and controls
157 lines (121 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import math
class RestaurantNode:
def __init__(self, name, stars, comment_nums):
self.name = name
self.rating = self.calculate_rating(stars, comment_nums)
self.left = None
self.right = None
self.height = 1
def calculate_rating(self, stars, comment_nums):
if comment_nums == 0:
return 3.0
weighted_score = (stars - 3.0) * (comment_nums / 1500) # 控制評論數量對評分的影響
rating = 3 + math.tanh(weighted_score) * 2 # 使用 tanh 函數調整評分範圍
return round(max(1, min(5, rating)), 3)
class RestaurantAVL:
def __init__(self):
self.root = None
def add_restaurant(self, name, stars, comment_nums):
new_node = RestaurantNode(name, stars, comment_nums)
self.root = self._insert(self.root, new_node)
def _insert(self, current, new_node):
if not current:
return new_node
if new_node.rating < current.rating:
current.left = self._insert(current.left, new_node)
elif new_node.rating > current.rating:
current.right = self._insert(current.right, new_node)
else:
# 忽略相同評分的情況
return current
current.height = 1 + max(self._get_height(current.left), self._get_height(current.right))
balance = self._get_balance(current)
# LL
if balance > 1 and new_node.rating < current.left.rating:
return self._rotate_right(current)
# RR
if balance < -1 and new_node.rating > current.right.rating:
return self._rotate_left(current)
# LR
if balance > 1 and new_node.rating > current.left.rating:
current.left = self._rotate_left(current.left)
return self._rotate_right(current)
# RL
if balance < -1 and new_node.rating < current.right.rating:
current.right = self._rotate_right(current.right)
return self._rotate_left(current)
return current
def _rotate_left(self, z):
y = z.right
T2 = y.left
y.left = z
z.right = T2
z.height = 1 + max(self._get_height(z.left), self._get_height(z.right))
y.height = 1 + max(self._get_height(y.left), self._get_height(y.right))
return y
def _rotate_right(self, z):
y = z.left
T3 = y.right
y.right = z
z.left = T3
z.height = 1 + max(self._get_height(z.left), self._get_height(z.right))
y.height = 1 + max(self._get_height(y.left), self._get_height(y.right))
return y
def _get_height(self, node):
if not node:
return 0
return node.height
def _get_balance(self, node):
if not node:
return 0
return self._get_height(node.left) - self._get_height(node.right)
def _inorder_traversal(self, node):
if not node:
return []
return self._inorder_traversal(node.left) + [node] + self._inorder_traversal(node.right)
# Add this method to the RestaurantAVL class in restaurant.py
def get_all_restaurants(self):
return self._inorder_traversal(self.root)
def search_by_rating(self, rating):
return self._search_by_rating(self.root, rating)
def _search_by_rating(self, current, rating):
if not current:
return None
if current.rating == rating:
return current
elif rating < current.rating:
return self._search_by_rating(current.left, rating)
else:
return self._search_by_rating(current.right, rating)
def print_tree(self):
def _print_tree(node, level=0):
if node:
_print_tree(node.right, level + 1)
print(' ' * 4 * level + '->', node.name, f"Rating: {node.rating}")
_print_tree(node.left, level + 1)
_print_tree(self.root)
def test():
restaurant_tree = RestaurantAVL()
print()
restaurant_tree.add_restaurant("鄰家早午餐", 4.5, 230)
restaurant_tree.print_tree()
print()
restaurant_tree.add_restaurant("gogobus", 4.8, 447)
restaurant_tree.print_tree()
print()
restaurant_tree.add_restaurant("明哥滷味(忠孝)", 4.6, 520)
restaurant_tree.print_tree()
print()
restaurant_tree.add_restaurant("品味", 3.9, 26)
restaurant_tree.print_tree()
print()
restaurant_tree.add_restaurant("龍哥", 3.6, 120)
restaurant_tree.print_tree()
print()
restaurant_tree.add_restaurant("沒料鐵哥", 2.9, 364)
restaurant_tree.print_tree()
result = restaurant_tree.search_by_rating(4.66)
if result:
print(f"找到餐廳: {result.name}, 評分: {result.rating}")
else:
print("找不到該評分的餐廳")