As you know now, a queue is a data structure where the first item placed in the structure is the first item taken out of the structure. This means that the oldest item in the structure is removed first. Many applications, though, require a data structure where an item with the highest priority is removed first, even if it isn’t the “oldest” item in the structure. There is a
special case of the Queue made for this type of application—the priority queue.
There are many applications that utilize priority queues in their operations. A good example is process handling in a computer operating system. Certain processes have a higher priority than other processes, such as printing pro- cesses, which typically have a low priority. Processes (or tasks) are usually numbered by their priority, with a Priority 0 process having a higher priority than a Priority 20 task.
Items stored in a priority queue are normally constructed as key–value pairs, where the key is the priority level and the value identifies the item. For example, an operating system process might be defined like this:
Structure Process
Dim Priority As Integer Dim Name As String End Structure
We cannot use an unmodified Queue object for a priority queue. The DeQueue method simply removes the first item in the queue when it is called. We can, though, derive our own priority queue class from the Queue class, overriding Dequeue to make it do our bidding.
We’ll call the class PQueue. We can use all of the Queue methods as is and override the Dequeue method to remove the item that has the highest priority. To remove an item from a queue that is not at the front of the queue, we have to first write the queue items to an array. Then we can iterate through the array to find the highest priority item. Finally, with that item marked, we can rebuild the queue, leaving out the marked item.
Here’s the code for the PQueue class: Public Structure pqItem
Dim Priority As Integer Dim Name As String End Structure
Public Class PQueue Inherits Queue Public Sub New()
MyBase.new() End Sub
Queues, the Queue Class, and a Queue Class Implementation 121
Public Overrides Function Dequeue() As Object Dim items() As Object
Dim x, min, minindex As Integer
items = Me.ToArray 'changes the queue to an array min = CType(items(0), pqItem).Priority
For x = 1 To items.GetUpperBound(0)
If (CType(items(x), pqItem).Priority < min) Then min = CType(items(x), pqItem).Priority
minindex = x End If
Next
Me.Clear() 'Clears the queue
For x = 0 To items.GetUpperBound(0)
If (x <> minindex And CType(items(x), pqItem). _ Name <> "") Then
Me.Enqueue(items(x)) 'rebuild the queue End If
Next
Return items(minindex) End Function
End Class
Let’s consider a specific example. An emergency waiting room assigns a priority to patients who come in for treatment. A patient presenting symp- toms of a heart attack is going to be treated before a patient who has a bad cut. The following program simulates three patients entering an emer- gency room at approximately the same time. Each patient is seen by the triage nurse, assigned a priority, and added to the queue. The first pa- tient to be treated is the patient removed from the queue by the Dequeue method. The following code demonstrates this simple use of the PQueue class:
Sub Main()
Dim erwait As New PQueue() Dim erPatient(4) As pqItem Dim nextPatient As pqItem Dim x As Integer
erPatient(0).Name = "Joe Smith" erPatient(0).Priority = 1
erPatient(1).Name = "Mary Brown" erPatient(1).Priority = 0
erPatient(2).Name = "Sam Jones" erPatient(2).Priority = 3 For x = 0 To erPatient.GetUpperBound(0) erwait.Enqueue(erPatient(x)) Next nextPatient = erwait.Dequeue Console.WriteLine(nextPatient.Name) Console.Write("Press enter") Console.Read() End Sub
The output of this program is “Mary Brown,” since she has a higher priority than the other patients.
SUMMARY
Learning to use data structures appropriately and efficiently is one of the skills that separates the expert programmer from the average one. The expert programmer recognizes that organizing a program’s data into an appropriate data structure makes it easier to work with the data. In fact, thinking through a computer programming problem using data abstraction makes it easier to come up with a good solution to the problem in the first place.
We looked at using two very common data structures in this chapter— the stack and the queue. Stacks are used for solving many different types of problems in computer programming, especially in systems programming areas such as interpreters and compilers. We also saw how we can use stacks to solve more generic problems, such as determining if a word is a palindrome.
Queues also have many applications. Operating systems use queues for ordering processes (via priority queues) and queues are used quite often for simulating real-world processes. Finally, we used the Queue class to derive a class for implementing a priority queue. The ability to derive new classes from classes in the .NET Framework class library is one of the major strengths of the .NET version of Visual Basic.
Exercises 123
EXERCISES
1. You can use a Stack to check whether a programming statement or a formula has balanced parentheses. Write a Windows application that provides a textbox for the user to enter an expression with parenthesis. Provide a Check Parens button that, when clicked, runs a program that checks the number of parentheses in the expression and highlights a parenthesis that is unbalanced.
2. A postfix expression evaluator works on arithmetic statements that take the following form:
op1 op2 operator. . .
Using two stacks, one for the operands and one for the operators, design and implement a Calculator class that converts infix expressions to postfix expressions and then uses the stacks to evaluate the expressions.
3. Design a help-desk priority manager. Store help requests stored in a text file with the following structure:
priority, id of requesting party, time of request
The priority is an integer in the range 1–5 with 1 being the least important and 5 being the most important. The id is a four-digit employee identi- fication number and the time is in TimeSpan.Hours, TimeSpan.Minutes, TimeSpan.Seconds format. Write a Windows application that, during the Form Load event, reads five records from the data file containing help re- quests, prioritizes the list using a priority queue, and displays the list in a list box. Each time a job is completed, the user can click on the job in the list box to remove it. When all five jobs are completed, the applica- tion should automatically read five more data records, prioritize them, and display them in the list box.
CH A P T E R
6
The BitArray Class
T
he BitArray class is used to represent sets of bits in a compact fashion. Bit sets can be stored in regular arrays, but we can create more efficient programs if we use data structures specifically designed for bit sets. In this chapter we’ll look at how to use this data structure and examine some problems that can be solved using sets of bits.Since many VB.NET programmers have not been properly introduced to working with binary numbers, this chapter also includes a review of binary numbers, bitwise operators, and bitshift operators.