DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING
LAB MANUAL
Academic Year: 2025-2026 ODD SEMESTER
Program (UG/PG) : UG
Semester : I
Course Code : SEC-ECE306
Course title : Data Structures using Python Laboratory
Prepared by,
JAYANTHI HARINI
Assistant Professor
Department of Computer Science & Engineering
HARDWARE AND SOFTWARE REQUIREMENTS
HARDWARE REQUIREMENTS:
INTEL PENTIUM 915 GV
80GB HDD
512MB DDR
SOFTWARE REQUIREMENTS:
PYTHON
Internal and External Marks Split Up
Program Execution : 5 marks
Output : 5 marks
Script : 10 marks
Viva : 10 marks
Record Book : 20 marks
Internal Examination : 50 marks
External Examination : 50 marks
TOTAL MARKS : 100 marks
Steps to install Python on Windows
Installing Python on Windows is a straightforward process. Please follow these steps to set up
Python on your system:
Step 1: Download the Python Installer
Visit the official Python website and navigate to the Downloads section.
Select the latest stable version of Python for Windows (e.g., Python 3.x).
Choose the appropriate installer based on your system architecture: 64-bit: Windows installer (64-
bit) 32-bit: Windows installer (32-bit)
Download the .exe file.
Step 2: Run the Installer
Locate the downloaded .exe file (e.g., [Link]) and double-click it.
In the installer window: Check the box for Add Python to PATH (important for command-line usage).
Click Install Now for a default installation or choose Customize Installation for advanced options.
Step 3: Complete Installation
Wait for the installation process to finish.
Once completed, you’ll see a success message. Close the installer.
Step 4: Verify Installation
Open Command Prompt or PowerShell.
Type the following command to check if Python is installed:
python --version
Tips
Use pip, Python's package manager, to install additional libraries:
python -m pip install <package_name>
For coding, you can use Python's built-in IDLE or install an IDE like PyCharm or VS Code.
You’re now ready to start coding in Python!
Steps to execute a Python program
To implement a Python program:
1. Install Python
• Download and install Python from the official Python website.
• Ensure Python is added to your system's PATH during installation.
2. Set Up Your Environment
• Use an IDE or text editor like PyCharm, VS Code, or IDLE.
• Alternatively, you can write code in a simple text editor and run it via the terminal.
3. Write Your Code
• Create a new file with the .py extension (e.g., [Link]).
• Write your Python code. For example:
• Copy codeprint("Hello, World!")
4. Run the Program
• Open a terminal or command prompt.
• Navigate to the directory containing your .py file.
• Execute the program using:
• Copy codepython [Link]
5. Debug and Test
• Check for syntax errors or logical issues.
• Use debugging tools or print() statements to trace errors.
6. Enhance and Optimize
• Refactor your code for readability and efficiency.
• Add comments and documentation for clarity.
7. (Optional) Use Libraries
• Install libraries using pip if needed:
• Copy codepip install library_name
• Import and use them in your program.
8. Save and Share
• Save your program and share it with others or deploy it as needed.
This process is beginner-friendly and adaptable for more complex projects as you grow in Python!
ADIKAVI NANNAYYA UNIVERSITY, RAJAHMUNDRY
LIST OF EXPERIMENTS AND SCHEDULE
Course Code : SEC-ECE306
Course Title : Data Structures using Python Laboratory
Serial Number Date Experiment Page Number
1 24-07-2025 Constructors 7
2 31-07-2025 Inheritance Hierarchy and Abstraction 8
3 07-08-2025 Method Overloading & Method Overriding 9
4 14-08-2025 Comprehension: List, Dictionary, Set, Generator 10
5 21-08-2025 Generate set of n distinct objects from list. 11
6 28-08-2025 Linear search and binary search 12
7 04-09-2025 Bubble sort and Selection sort 13
8 11-09-2025 Merge sort and Quick sort 14
9 18-09-2025 Stacks and Queues 15
10 25-09-2025 Singly Linked List 16
11 02-10-2025 Doubly Linked List 17
12 09-10-2025 Binary Search Tree 18
Program Number : 01
Program Date : 24-07-2025
Program Title : Constructors
Aim : To create a class ‘Flower’ with Name (String), Number
Of Petals (Integer) and Price (Float) and create various instances
Definition : In Python, a class is a collection of similar objects.
Explanation : Python is an object-oriented language. Everything in python is
Considered as object with its own properties and methods
Syntax : To create class: Class Class_name:
ClassVariable = “Value”
Constructor: Def _init_(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
Function Initialization: object1 = class_name()
Understanding self in Python: In Python, self is a conventionally used
parameter in instance methods of a class. It represents the instance
of the class and allows access to its attributes and methods.
Key Points About self:
Refers to the Current Instance: self refers to the specific object that
is calling the method. It allows you to access and modify the attributes
of that particular instance.
Not a Reserved Keyword: While self is widely used, it is not a
reserved keyword. You can use any name, but sticking to self is a best
practice for readability and consistency.
Mandatory in Instance Methods: The first parameter of any instance
method must refer to the instance itself, and self is used for this
purpose.
Output : print([Link])
Program : class flower: #classname
name = input("Please enter the name of the flower: ")
numberofpetals = input("Please enter number of petals: ")
price = input("Please enter the price: ")
def _init_(self, name, numberofpetals, price):
[Link] = name
[Link] = numberofpetals
[Link] = price
#class intialization
flowerobj = flower()
print("The name of the flower is: ", [Link])
print("The number of petals of the flower is:
",[Link])
print("The price of the flower is: ",[Link])
Output : Please enter the name of the flower: Rose
Please enter the number of petals of the flower: 9
Please enter the price of the flower: 1.00
The name of the flower is: Rose
The number of petals of the flower is: 9
The price of the flower is: 1.00
Conclusion : Classes and Objects implemented using Python Programming
Program Number : 02
Program Date : 31-07-2025
Program Title : Polygons using Inheritance Hierarchy and Abstraction
Aim : To implement inheritance hierarchy and abstraction concepts
Definition : Inheritance concept is where there is a parent class with
attributes and methods, and child class inherits all the attributes and
methods of parent class and has its own attributes and methods.
Abstraction is a concept where implementation details are hidden
and only essential details of the object are revealed.
Explanation : Inheritance is an object oriented concept, which help the
programmer to inherit or access parent class attributes and methods
from child class which inherits parent class.
Abstraction is also an object oriented concept, where the
programmer can hide implementation details from the user and
display only essential features of the class.
Syntax : Class ParentClass():
ParentClassAttributes declaration
ParentClassMethods declaration
Class ChildClass(ParentClass):
ChildClassAttribute declaration
ChildClassMethod declaration
ChildClassObj = ChildClass()
[Link]
[Link]()
Program : class ply():
def area(self):
pass
def perimeter(self):
return "PERIMETER"
class trn(ply):
base = input("Please enter the base value of the triangle in
centimeters: ")
height = input("Please enter the height value of the triangle in
centimeters: ")
def _init_(self,base,height):
[Link] = base
[Link] = height
def area(self):
return (1/2)*float([Link])*float([Link])
def perimeter(self):
return 3*float([Link])
trl = trn()
print("The area of the triangle is: ", [Link](), "sqcm")
print("The perimeter of the triangle is: ", [Link](), "cm")
Output : Please enter the base value of the triangle in centimetres: 10
Please enter the height value of the triangle in centimetres: 6
The area of the triangle is: 35.0 [Link]
The perimeter of the triangle is: 30.0 cm
Conclusion : Hence, Inheritance and abstraction implemented.
Program Number : 03
Program Date : 07-08-2025
Program Title : Method Overloading and Method Overriding
Aim : To implement method overloading and method overriding concepts
Definition : Method Overloading: Method overloading is to define multiple
methods with same name but different set of arguments.
Method Overriding: Method overriding is to implement the methods
by the child class inherited from parent class thereby customize
according the child class.
Explanation : In Python, Method overloading is an object oriented concept that
does not allow multiple methods with the same name but different
parameters. One can achieve similar functionality using default
arguments, variable-length arguments, or libraries like function
tools for multiple dispatch.
Method overriding is an object-oriented concept to customize
inherited methods according the child class
Same Method Name: The method in the subclass must have the same
name as the one in the superclass.
Same Parameters: The method signature (parameters) should match
the superclass method.
Dynamic Dispatch: When the method is called on an object, Python
determines which version of the method to execute based on the
object's type.
Syntax : class classname:
#method declaration
classinstance = classname()
Print([Link](variable number of arguments))
Program : Overloading:
class calculator:
def add(self,a,b=0,c=0):
return a+b+c
calc = calculator()
print([Link](5))
print([Link](5,10))
print([Link](5,10,15))
Overriding:
class parent:
def greet(self):
print("Hello from the parent class")
class child(parent):
def greet(self):
print("Hello from the child class")
obj = child()
print([Link]())
Output : Method overloading:
5
10
15
Method overriding:
Hello from the Child class
Conclusion : Hence, method overloading and method overriding implemented.
Program Number : 04
Program Date : 14-08-2025
Program Title : List, Dictionary, Set & Generator Comprehensions
Aim : To implement Comprehensions using Python
Definition : Comprehensions create and manipulate data structures (lists,
Dictionary, sets) from set of iterables using expressions & conditions.
List Comprehension: Create a list of elements by applying an
expression from the existing iterables
Dictionary Comprehension: Create a dictionary by applying an
expression to key-value pairs
Set Comprehension: Create a set of elements by applying an
expression to an existing iterables
Generator Comprehension: To create a generator object.
Explanation : In Python, comprehensions are often preferred for their simplicity
and efficiency.
Advantages of Comprehensions:
• Concise: Reduces the number of lines of code.
• Readable: Easier to understand compared to traditional loops.
• Efficient: Often faster than equivalent loops.
Uses:
• For simple transformations or filtering of data.
• Avoid for complex logic, as they can reduce code readability
Syntax : List Comprehension
new_list = [expression for item in iterable if condition]
Dictionary Comprehension
new_dict = {key_expression: value_expression for item in iterable if
condition}
Set Comprehension
new_set = {expression for item in iterable if condition}
Generator Comprehension
generator = (expression for item in iterable if condition)
Program : num_list = [1,2,3,4,5]
print ("Input list: ", num_list)
e_num = [x for x in num_list if x % 2 == 0]
print ("List Comprehension: ", e_num)
myDict = {x: x**2 for x in num_list }
print ("Dictionary Comprehension: ", myDict)
newSet = {p: p**3 for p in num_list if p%2 == 1}
print ("Set Comprehension: ",newSet)
genList = (a*2 for a in num_list if a % 2 == 0)
print ("Generator Comprehension: ")
for ele in genList:
print(ele)
Output : Input list: [1, 2, 3, 4, 5]
List Comprehension (Even Numbers): [2, 4]
Dictionary Comprehension (Squares): {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Set Comprehension (Cubes): {1: 1, 3: 27, 5: 125}
Generator Comprehension:
4
8
Conclusion : Hence, comprehensions implemented.
Program Number : 05
Program Date : 21-08-2025
Program Title : Generate set of n distinct objects from list of elements
Aim : To generate set of n distinct objects from the given list of elements
Definition : Distinct Object:
To select distinct object from the Universal list is to select elements
without repetition/remove duplicates/unique selection.
Explanation : When a list of elements is given, select the elements by set of two
at a time, without repeating values. There are several methods
(list, dictionary, set comprehensions) to select distinct objects from a
given set using Python. Each method ensures the resulting list
contains only distinct elements. Note that the order of elements may
vary depending on the approach used.
Syntax : list_name = [list of elements separated by comma (,)]
distinct_list = list(set(list_name))
print(distinct_list)
Program : from itertools import combinations
number_list = [1,2,3,4,5]
dis_elm = []
#for r in range(1,len(number_list)+1):
dis_elm.extend(combinations(number_list, 2))
for elm in dis_elm:
print(elm)
Output : [1, 2]
[1, 3]
[1, 4]
[1, 5]
[2, 3]
[2, 4]
[2, 5]
[3, 4]
[3, 5]
[4, 5]
Conclusion : Hence distinct object set is selected
Program Number : 06
Program Date : 28-08-2025
Program Title : Linear Search and Binary Search
Aim : To implement linear search and binary search
Definition : Linear search: Linear Search is an algorithm that checks each
element in a sorted list sequentially until search element is found.
Binary search: Binary Search is an efficient algorithm used to find
the position of a target element within a sorted array or list ends.
Explanation : Given a list of similar elements in sorted manner, linear search is an
approach to search a search value in a sequential manner. All
elements in the collection is parsed in a sequential manner to find the
search element, till it is found or not found. Given a collection of
similar objects in sorted form, binary search first arranges all the
elements in a Binary tree format, then it implements binary tree
search method to find the search value, or the element doesn’t not
exist.
Syntax : Array:
array_name = [Link](typecode, [elements])
For loop:
for index, value in enumerate(list):
#instructions to be executed as value is within the list
Program : arr = [1,2,3,4,5,6,7,8,9]
print("The sorted input list is: ", arr)
schkey = input("Please enter the search key value: ")
def lnsch(lnarr, lnschkey):
for index, elm in enumerate(lnarr):
if int(elm) == int(lnschkey):
return "Element found using linear search"
return "Element not found in linear search"
lnschresult = lnsch(arr,schkey)
print(lnschresult)
def bnysch(bnyarr, bnyschkey):
lw = 1
hg = 9
for index in enumerate(bnyarr):
mid = int(lw + hg) /2
if int(bnyschkey) < int(mid):
hg = int(mid)
elif int(bnyschkey) > int(mid):
lw = int(mid)
else:
return "Element found using binary search"
return "Element not found in binary search"
bnyresult = bnysch(arr,schkey)
print(bnyresult)
Output : The sorted input list is: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Please enter the search key value: 4
Element found using linear search
Element found using binary search
Conclusion : Hence, linear search and binary search implemented
Program Number : 07
Program Date : 04-09-2025
Program Title : Bubble sort and Selection Sort
Aim : To implement Bubble sort and Selection sort
Definition : Sort is to arrange all elements in ascending or descending order.
Swap is to exchange positions of two elements in the given list.
Bubble Sort is a basic technique by which, adjacent elements
are compared and swapped, if found unordered, repeatedly till the
whole list is ordered.
Selection Sort is a simple technique, by which smallest element is
swapped with the first element of the (remaining) unsorted list
repeatedly till the whole list is ordered.
Explanation : Bubble Sort is a simple sorting algorithm that repeatedly steps
through the list, compares adjacent elements, and swaps them if
they are in the wrong order. This process is repeated until the list is
sorted.
Selection Sort is a simple and intuitive algorithm. By dividing the
array into sorted portion and the unsorted portion. The algorithm
repeatedly selects the element from the unsorted portion and
swaps it with the first element of the unsorted portion. This process
continues until the entire array is sorted.
Syntax : Array:
array_name = [Link](typecode, [elements])
Nested for Loop:
for outer_variable in outer_sequence:
for inner_variable in inner_sequence:
# Code block to execute
Program : import array
class sortclass:
list = [4,2,6,8,3,9,1,5,7]
def bubblesort(self, list):
for outerloopvariable in range(len(list)):
for innerloopvariable in range(len(list)):
if list[innerloopvariable] > list[outerloopvariable]:
list[outerloopvariable], list[innerloopvariable] =
list[innerloopvariable], list[outerloopvariable]
return list
def selectionsort(self, list):
for i in range(len(list)):
for j in range(len(list)):
if list[i] > list[j]:
list[i], list[j] = list[j], list[i]
return list
sortobj = sortclass()
print("The input unordered list is: ", [Link])
print("Bubble sort: ", [Link]([Link]))
print("Selection sort: ", [Link]([Link]))
Output : The input unordered list is: [4, 2, 6, 8, 3, 9, 1, 5, 7]
Bubble sort: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Selection sort: [9, 8, 7, 6, 5, 4, 3, 2, 1]
Conclusion : Hence Bubble sort and Selection sort implemented
Program Number : 08
Program Date : 11-09-2025
Program Title : Merge Sort and Quick Sort
Aim : To implement Merge sort and Quick sort
Definition : Merge Sort is an stable technique to divide given list of elements
into two sub-lists, sort and merge into single sorted list.
Quick Sort is a divide-and-conquer technique that selects a pivot
and partitions the list around it.
Explanation : Divide & Conquer is to recursively split into halves until each sub-
lists contain a single element and merged back together into sorted
order.
Syntax : while condition:
# Code block to execute
Program : def merge_sort(arr):
if len(arr) > 1: mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
merge_sort(left_half)
merge_sort(right_half)
i=j=k=0
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
arr[k] = left_half[i]
i += 1
else: arr[k] = right_half[j]
j += 1
k += 1
while i < len(left_half):
arr[k] = left_half[i]
i += 1
k += 1
while j < len(right_half):
arr[k] = right_half[j]
j += 1
k += 1
if __name__ == "__main__": arr = [2,7,4,9,1,6,3,8,5]
print("The unordered input array is: ", arr)
merge_sort(arr)
print("The elements sorted using merge sort is: ", arr)
def quicksort(arr):
if len(arr) <= 1: return arr
else: lesspivot = [x for x in arr[1:] if x > arr[0]]
greaterpivot = [x for x in arr[1:] if x <= arr[0]]
return quicksort(lesspivot)+[pivot]quicksort(greaterpivot)
unsorted_array = [2,7,4,9,1,6,3,8,5]
array = quick_sort(unsorted_array)
print("The elements sorted using quick sort is: ", array)
Output : The unordered input array is: [2, 7, 4, 9, 1, 6, 3, 8, 5]
The elements sorted using merge sort is: [1, 2, 3, 4, 5, 6, 7, 8, 9]
The elements sorted using quick sort is: [9, 8, 7, 6, 5, 4, 3, 2, 1]
Conclusion : Hence merge sort and quick sort implemented
Program Number : 09
Program Date : 18-09-2025
Program Title : Stacks and Queues implementation
Aim : To implement stack and queues concepts
Definition : A Stack is a linear data structure that stores items in a Last-In/First-
Out (LIFO) or First-In/Last-Out (FILO) manner.
A Queue is a linear data structure that follows the (FIFO) principle
Explanation : In stack, a new element is added at one end and an element is
removed from that end only. The insert and delete operations are
often called push and pop.
A queue is a linear data structure that follows the First-In-First-Out
(FIFO) principle, meaning the first element added is the first one to
be removed. Queues are widely used in scenarios like task
scheduling, breadth-first search in graphs, and message queues.
Syntax : empty() – Returns whether the stack is empty
size() – Returns the size of the stack
top() / peek() – Returns a reference to the topmost element of the
[Link](a) – Inserts the element at the top of the stack
pop() – Deletes the topmost element of the stack
[Link]('A') # Enqueue
queue[0] # Peek
[Link](0) # Dequeue
not bool(queue) # isEmpty
len(queue) # Size
Program : stack = []
print("Stack Implementation: ")
print("Initial Stack: ", stack)
[Link](10)
print("Stack after push operation: ", stack)
print("Pop Element: ", [Link]()) # Output: 30
print("Stack after pop operation: ", stack)
print("Is empty: ", len(stack) == 0) # Output: False
queue = []
print("\nQueue")
[Link]('a')
[Link]('b')
[Link]('c')
print("Initial Queue:", queue)
print("Dequeued Element:", [Link](0))
print("Queue after Dequeue:", queue)
Output : Stack Implementation:
Initial Stack: []
Stack after push operation: [10]
Pop Element: 10
Stack after pop operation: []
Is empty: True
Queue
Initial Queue: ['a', 'b', 'c']
Dequeued Element: a
Queue after Dequeue: ['b', 'c']
Conclusion : Hence stacks and Queues implemented
Program Number : 10
Program Date : 25-09-2025
Program Title : Singly Linked List implementation
Aim : To implement singly linked list concept
Definition : A singly linked list is a linear data structure where each element
contains data, next pointer
Explanation : In a singly linked list:
Node: Represents an element
Data: The value stored in the node.
Next Pointer: A reference (or link) to the next node in the sequence.
Nodes are connected in a sequential manner. The last node's next
pointer is set to None, indicating the end of the list. Traversal is
possible only in one direction, from the head (first node) to the tail
(last node).
Syntax : [Link] = None # Pointer to the next node
[Link] = None # Initialize the head of the list
[Link] = None # Pointer to the previous node
linked_list.append(30)
linked_list.display() # Output
Program : class Node:
def __init__(self, data):
[Link] = data # Store data
[Link] = None # Initialize next as None
class SinglyLinkedList:
def __init__(self):
[Link] = None # Initialize the head of the list
def append(self, data):
new_node = Node(data)
if not [Link]: # If the list is empty
[Link] = new_node
return current = [Link]
while [Link]: # Traverse to the end of the list
current = [Link]
[Link] = new_node # Link the new node at the end
def display(self):
current = [Link]
while current:
print([Link], end=" -> ")
current = [Link]
print("None")
sll = SinglyLinkedList()
[Link](10)
[Link](20)
[Link](30)
[Link]() # Output: 10 -> 20 -> 30 -> None
Output : 10 -> 20 -> 30 -> None
Conclusion : Hence Singly Linked list implemented
Program Number : 11
Program Date : 02-10-2025
Program Title : Doubly Linked List implementation
Aim : To implement doubly linked list concept
Definition : A Doubly Linked List in Python is a type of linked list where each
Element contains Data, Next pointer, previous pointer.
Explanation : Data: The value stored in the node.
Next Pointer: A reference to the next node in the sequence.
Previous Pointer: A reference to the previous node in the sequence.
This structure allows traversal in both forward and backward
directions, making operations like insertion, deletion, and traversal
more efficient compared to a singly linked list.
1. Node Class: Represents each node with data, prev (pointer to
the previous node), and next (pointer to the next node).
2. DoublyLinkedList Class: Manages the list with operations like
appending and traversing.
3. Traversal: You can traverse the list in both forward and
backward directions.
This is a simple implementation, and you can expand it with more
operations like insertion at specific positions, deletion, etc.
Syntax : dll.display_forward()
dll.display_backward()
Program : class Node:
def __init__(self, data):
[Link] = data
[Link] = None
[Link] = None
class DoublyLinkedList:
def __init__(self): [Link] = None
def append(self, data): new_node = Node(data)
if not [Link]:
[Link] = new_node
return
temp = [Link]
while [Link]:
temp = [Link]
[Link] = new_node
new_node.prev = temp
def display(self): temp = [Link]
while temp:
print([Link], end=" <-> ")
temp = [Link]
print("None")
# Example usage
dll = DoublyLinkedList()
[Link](10)
[Link](20)
[Link](30)
[Link]()
Output : 10 <-> 20 <-> 30 <-> None
Conclusion : Hence, Doubly Linked list implemented
Program Number : 12
Program Date : 09-10-2025
Program Title : Binary Search Tree implementation
Aim : To implement binary search tree concept
Definition : A Binary Tree is a hierarchical data structure where each node has
utmost two children, left child and right child.
Explanation : The topmost node is called the root, and nodes without children are
called leaves. Binary trees are widely used for efficient data storage,
retrieval, and manipulation. The left and right sub-trees of a node
are binary trees themselves. Common types :Full, Complete, Perfect
and Balanced Binary Trees.
In-order Traversal (Left, Root, Right): To retrieve sorted data.
Pre-order Traversal (Root, Left, Right): For creating a copy of tree.
Post-order Traversal (Left, Right, Root): For deleting a tree.
Syntax : class ClassName:
def method_name(*args): # method statements
Program : class Node:
def __init__(self, data):
[Link] = data
[Link] = None
[Link] = None
root = Node(1)
[Link] = Node(2)
[Link] = Node(3)
[Link] = Node(4)
[Link] = Node(5)
def in_order_traversal(node):
if node is None: return
in_order_traversal([Link])
print([Link], end=" ")
in_order_traversal([Link])
def pre_order_traversal(node):
if node is None: return
print([Link], end=" ")
pre_order_traversal([Link])
pre_order_traversal([Link])
def post_order_traversal(node):
if node is None: return
post_order_traversal([Link])
post_order_traversal([Link])
print([Link], end=" ")
print("In-order Traversal: ", end="")
in_order_traversal(root)
print("\nPre-order Traversal: ", end="")
pre_order_traversal(root)
print("\nPost-order Traversal: ", end="")
post_order_traversal(root)
Output : In-order Traversal: 4 2 5 1 3
Pre-order Traversal: 1 2 4 5 3
Post-order Traversal: 4 5 2 3 1
Conclusion : Hence Binary tree concept implemented