MIS309 Algorithms and Data Structures Lecture 2 PDF
Document Details
Uploaded by Deleted User
Haliç University
Alaaddin Baharoğlu PhD.
Tags
Summary
This lecture provides an overview of arrays and time complexity analysis in C#. It explains how arrays are used for organizing data and the different time complexities algorithms can exhibit, especially when implemented in C#. The document details array operations, such as accessing elements, sorting, adding elements and removal of elements.
Full Transcript
MIS309 ALGORITHMS AND DATA STRUCTURES By Alaaddin Baharoğlu PhD. (c) Lecture 2 A r r a y s , Ti m e C o m p l e x i t y ( Ru n Ti m e Analysis) ARRAYS ARRA YS...
MIS309 ALGORITHMS AND DATA STRUCTURES By Alaaddin Baharoğlu PhD. (c) Lecture 2 A r r a y s , Ti m e C o m p l e x i t y ( Ru n Ti m e Analysis) ARRAYS ARRA YS An array is a data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type. Usage: Arrays are used for organizing data in a systematic manner and facilitate operations like sorting, searching, etc. ARRA YS Arrays are declared by specifying the type of their elements, followed by square brackets, and then the array name. Examples: int[] numbers; string[] names; You can initialize an array either by specifying its size or by directly initializing it with elements: int[] numbers = new int; string[] names = {"Alice", "Bob", "Charlie"}; ARRA YS You can access the elements of an array by specifying the index of the desired element enclosed between [ ]. Example: String firstName = names; firstName now has : “Alice” ARRA YS C# supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array. Example: int[,] matrix = new int[3,4]; 3 rows 4 cols ARRAYS OPERATIONS Length Property: returns the total number of elements in the array. Looping Through an Array: You can use loops to access each element in the array. Sorting an Array: The Array.Sort() method is used for sorting the array elements. Ascending EXAMPLES EXAMPLE 1 EXAMPLE 2 CREATE AN ARRAY OF 5 CREATE A STRING ARRAY OF 3 INTEGERS AND PRINT THEM IN STUDENT NAMES AND DISPLAY REVERSE ORDER THEM USING A FOREACH LOOP DYNAMICAL ARRAYS IN C# DYNAMICAL ARRAYS IN C# n C# you can use dynamic or resizable arrays, which are represented by the List class from the System.Collections.Generic namespace. Unlike arrays, lists do not have a fixed size and can dynamically adjust their size as elements are added or removed. Initialization: To use lists in C#, you need to include the System.Collections.Generic namespace. Here's an example of how you might declare and initialize a List: using System.Collections.Generic; List numbers = new List(); DYNAMICAL ARRAYS IN C# Adding Elements: numbers.Add(1); Accessing Elements: int firstNumber = numbers; Removing Elements: numbers.Remove(2); // Removes the first occurrence of 2 Removing Elements: numbers.RemoveAt(0); // Removes the element at index 0 DYNAMICAL ARRAYS IN C# (SPECIAL TYPES) Concurrent Collections: C# also provides thread-safe or concurrent collection classes, which are safe to be used by multiple threads concurrently. Examples include ConcurrentDictionary, ConcurrentQueue, and ConcurrentStack. Immutable Collections: These collections, once created, cannot be altered and are found in the System.Collections.Immutable namespace. Examples include ImmutableArray, ImmutableList, and ImmutableDictionary Observable Collections: It represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. Each type of collection is designed to facilitate specific use cases, and the best type of collection to use depends on the specific requirements of the operation you’re implementing. This rich set of collections enables developers to select the most efficient data structure for their applications, enhancing performance and functionality. TIME COMPLEXITY TIME COMPLEXITY AND RUN-TIME ANALYSIS Time Complexity is a metric that describes the amount of computational time taken by an algorithm It provides us with the insight to estimate how the execution time increases as the size of the input grows. It's often expressed using Big O notation, which describes the upper bound of the time complexity in the worst-case scenario. FUNDAMENTAL TIME COMPLEXITIES MEMORIZE THESE ! FUNDAMENTAL TIME COMPLEXITIES O(1): Constant Time - The algorithm takes a constant amount of time, regardless of the input size. Example: Accessing an array element by index. O(log n): Logarithmic Time - The algorithm runs in logarithmic time and is often seen in algorithms that decrease the input data size at each step. Example: Binary search. O(n): Linear Time - The running time increases linearly with the size of the input. Example: For loop that iterates through an array. FUNDAMENTAL TIME COMPLEXITIES O(n log n): Linearithmic Time - Algorithms that divide the input data in each step and work upon it linearly. Example: Merge sort and heapsort. O(n^2), O(n^3),..., O(n^k): Polynomial Time - These complexities are often seen in algorithms with nested loops where one or more loops traverse the entire input. Example: Bubble sort (O(n^2)) or three nested loops (O(n^3)). O(2^n): Exponential Time - The running time doubles with each additional element in the input data set. Example: Recursive calculation of Fibonacci numbers. O(n!): Factorial Time - The running time grows factorial, based on the input. Example: Solving the travelling salesman problem via a brute-force approach. ANALYZING TIME COMPLEXITY IN C# While analyzing algorithms in C# (or any language), you observe your code's structure to determine its efficiency. You generally consider the worst-case time complexity (largest possible amount of time taken) to ensure that the algorithm will run efficiently even in the most complex scenarios. WHY IS TIME COMPLEXITY IMPORTANT? Optimization: Helps in optimizing code to ensure it runs efficiently. Scalability: It helps in evaluating whether the algorithm will scale and remain efficient as the input grows. Comparative Analysis: Provides a metric for comparing the efficiency of different algorithms. IMPORTANT Usually, we are interested in the worst-case scenario (the highest order of growth), which is why Big O notation is commonly used. Low time complexity does not always translate to a fast algorithm, it just ensures that the algorithm remains efficient as the input grows. Time complexity is not the only factor to consider when optimizing algorithms. Other factors, such as space complexity, also play an essential role. Understanding time complexity and utilizing it during the algorithm design process is crucial for creating efficient applications, especially as they scale and handle larger datasets. THANK YOU See You Next Week