100% found this document useful (9 votes)
47 views

Instant Download Data Structures and Algorithms Using Python 1st Edition Rance D. Necaise PDF All Chapters

Using

Uploaded by

voorphytic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (9 votes)
47 views

Instant Download Data Structures and Algorithms Using Python 1st Edition Rance D. Necaise PDF All Chapters

Using

Uploaded by

voorphytic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Download the full version of the ebook at

https://ebookultra.com

Data Structures and Algorithms Using Python


1st Edition Rance D. Necaise

https://ebookultra.com/download/data-structures-
and-algorithms-using-python-1st-edition-rance-d-
necaise/

Explore and download more ebook at https://ebookultra.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Python for Everyone 2nd Edition Cay Horstmann. Rance


Necaise

https://ebookultra.com/download/python-for-everyone-2nd-edition-cay-
horstmann-rance-necaise/

ebookultra.com

Growing Algorithms and Data Structures 4th Edition David


Scuse

https://ebookultra.com/download/growing-algorithms-and-data-
structures-4th-edition-david-scuse/

ebookultra.com

Learning F Functional Data Structures and Algorithms 1st


Edition Masood

https://ebookultra.com/download/learning-f-functional-data-structures-
and-algorithms-1st-edition-masood/

ebookultra.com

Data Structures Algorithms In Go 1st Edition Hemant Jain

https://ebookultra.com/download/data-structures-algorithms-in-go-1st-
edition-hemant-jain/

ebookultra.com
Data structures using C 1st Edition Patil

https://ebookultra.com/download/data-structures-using-c-1st-edition-
patil/

ebookultra.com

Learning JavaScript Data Structures and Algorithms 2nd


Edition Loiane Groner

https://ebookultra.com/download/learning-javascript-data-structures-
and-algorithms-2nd-edition-loiane-groner/

ebookultra.com

Concise Notes on Data Structures and Algorithms Ruby


Edition Christopher Fox

https://ebookultra.com/download/concise-notes-on-data-structures-and-
algorithms-ruby-edition-christopher-fox/

ebookultra.com

Data Structures and Algorithms in Java 4th Edition Michael


T. Goodrich

https://ebookultra.com/download/data-structures-and-algorithms-in-
java-4th-edition-michael-t-goodrich/

ebookultra.com

Data Structures and Algorithms in Java 6th Edition Michael


T. Goodrich

https://ebookultra.com/download/data-structures-and-algorithms-in-
java-6th-edition-michael-t-goodrich/

ebookultra.com
Data Structures and Algorithms Using Python 1st Edition
Rance D. Necaise Digital Instant Download
Author(s): Rance D. Necaise
ISBN(s): 9780470618295, 0470618299
Edition: 1
File Details: PDF, 10.19 MB
Year: 2010
Language: english
This page intentionally left blank
Data Structures and
Algorithms Using
Python

Rance D. Necaise
Department of Computer Science
College of William and Mary

JOHN WILEY & SONS, INC.


ACQUISITIONS EDITOR Beth Golub
MARKETING MANAGER Christopher Ruel
EDITORIAL ASSISTANT Michael Berlin
SENIOR DESIGNER Jeof Vita
MEDIA EDITOR Thomas Kulesa
PRODUCTION MANAGER Micheline Frederick
PRODUCTION EDITOR Amy Weintraub

This book was printed and bound by Hamilton Printing Company. The cover was
printed by Hamilton Printing Company

This book is printed on acid free paper. ∞

Copyright ©2011 John Wiley & Sons, Inc. All rights reserved. No part of this
publication may be reproduced, stored in a retrieval system or transmitted in any
form or by any means, electronic, mechanical, photocopying, recording, scanning or
otherwise, except as permitted under Sections 107 or 108 of the 1976 United States
Copyright Act, without either the prior written permission of the Publisher, or
authorization through payment of the appropriate per-copy fee to the Copyright
Clearance Center, Inc. 222 Rosewood Drive, Danvers, MA 01923, website
www.copyright.com. Requests to the Publisher for permission should be addressed
to the Permissions Department, John Wiley & Sons, Inc., 111 River Street, Hoboken,
NJ 07030-5774, (201)748-6011, fax (201)748-6008, website
http://www.wiley.com/go/permissions.

“Evaluation copies are provided to qualified academics and professionals for review
purposes only, for use in their courses during the next academic year. These copies
are licensed and may not be sold or transferred to a third party. Upon completion
of the review period, please return the evaluation copy to Wiley. Return
instructions and a free of charge return shipping label are available at
www.wiley.com/go/returnlabel. Outside of the United States, please contact your
local representative.”

Library of Congress Cataloging-in-Publication Data

Necaise, Rance D.
Data structures and algorithms using Python / Rance D. Necaise.
p. cm.
Includes bibliographical references and index.
ISBN 978-0-470-61829-5 (pbk.)
1. Python (Computer program language) 2. Algorithms.
3. Data structures (Computer science) I. Title.
QA76.73.P98N43 2011
005.13'3—dc22 2010039903

Printed in the United States of America

10 9 8 7 6 5 4 3 2 1
To my nieces and nephews
Allison, Janey, Kevin, RJ, and Maria
This page intentionally left blank
Contents

Preface xiii

Chapter 1: Abstract Data Types 1


1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Abstractions . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1.2 Abstract Data Types . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.4 General Definitions . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 The Date Abstract Data Type . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 Defining the ADT . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.2 Using the ADT . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.3 Preconditions and Postconditions . . . . . . . . . . . . . . . 9
1.2.4 Implementing the ADT . . . . . . . . . . . . . . . . . . . . . 10
1.3 Bags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.3.1 The Bag Abstract Data Type . . . . . . . . . . . . . . . . . 15
1.3.2 Selecting a Data Structure . . . . . . . . . . . . . . . . . . 17
1.3.3 List-Based Implementation . . . . . . . . . . . . . . . . . . 19
1.4 Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.4.1 Designing an Iterator . . . . . . . . . . . . . . . . . . . . . 21
1.4.2 Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.5 Application: Student Records . . . . . . . . . . . . . . . . . . . . . 23
1.5.1 Designing a Solution . . . . . . . . . . . . . . . . . . . . . . 23
1.5.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 26
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Chapter 2: Arrays 33
2.1 The Array Structure . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.1.1 Why Study Arrays? . . . . . . . . . . . . . . . . . . . . . . . 34
2.1.2 The Array Abstract Data Type . . . . . . . . . . . . . . . . . 34
2.1.3 Implementing the Array . . . . . . . . . . . . . . . . . . . . 36
2.2 The Python List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

v
vi CONTENTS

2.2.1 Creating a Python List . . . . . . . . . . . . . . . . . . . . . 41


2.2.2 Appending Items . . . . . . . . . . . . . . . . . . . . . . . . 42
2.2.3 Extending A List . . . . . . . . . . . . . . . . . . . . . . . . 44
2.2.4 Inserting Items . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.2.5 List Slice . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.3 Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . 47
2.3.1 The Array2D Abstract Data Type . . . . . . . . . . . . . . . 47
2.3.2 Implementing the 2-D Array . . . . . . . . . . . . . . . . . . 49
2.4 The Matrix Abstract Data Type . . . . . . . . . . . . . . . . . . . . 52
2.4.1 Matrix Operations . . . . . . . . . . . . . . . . . . . . . . . 53
2.4.2 Implementing the Matrix . . . . . . . . . . . . . . . . . . . . 55
2.5 Application: The Game of Life . . . . . . . . . . . . . . . . . . . . . 57
2.5.1 Rules of the Game . . . . . . . . . . . . . . . . . . . . . . . 57
2.5.2 Designing a Solution . . . . . . . . . . . . . . . . . . . . . . 59
2.5.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 61
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Chapter 3: Sets and Maps 69


3.1 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.1.1 The Set Abstract Data Type . . . . . . . . . . . . . . . . . . 70
3.1.2 Selecting a Data Structure . . . . . . . . . . . . . . . . . . 72
3.1.3 List-Based Implementation . . . . . . . . . . . . . . . . . . 72
3.2 Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.2.1 The Map Abstract Data Type . . . . . . . . . . . . . . . . . 76
3.2.2 List-Based Implementation . . . . . . . . . . . . . . . . . . 77
3.3 Multi-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . 80
3.3.1 The MultiArray Abstract Data Type . . . . . . . . . . . . . . 81
3.3.2 Data Organization . . . . . . . . . . . . . . . . . . . . . . . 81
3.3.3 Variable-Length Arguments . . . . . . . . . . . . . . . . . . 85
3.3.4 Implementing the MultiArray . . . . . . . . . . . . . . . . . . 86
3.4 Application: Sales Reports . . . . . . . . . . . . . . . . . . . . . . 89
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

Chapter 4: Algorithm Analysis 97


4.1 Complexity Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . 97
4.1.1 Big-O Notation . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.1.2 Evaluating Python Code . . . . . . . . . . . . . . . . . . . . 104
4.2 Evaluating the Python List . . . . . . . . . . . . . . . . . . . . . . . 108
4.3 Amortized Cost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.4 Evaluating the Set ADT . . . . . . . . . . . . . . . . . . . . . . . . 113
CONTENTS vii

4.5 Application: The Sparse Matrix . . . . . . . . . . . . . . . . . . . . 115


4.5.1 List-Based Implementation . . . . . . . . . . . . . . . . . . 115
4.5.2 Efficiency Analysis . . . . . . . . . . . . . . . . . . . . . . . 120
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

Chapter 5: Searching and Sorting 125


5.1 Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.1.1 The Linear Search . . . . . . . . . . . . . . . . . . . . . . . 126
5.1.2 The Binary Search . . . . . . . . . . . . . . . . . . . . . . . 128
5.2 Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
5.2.1 Bubble Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.2.2 Selection Sort . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.2.3 Insertion Sort . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.3 Working with Sorted Lists . . . . . . . . . . . . . . . . . . . . . . . 142
5.3.1 Maintaining a Sorted List . . . . . . . . . . . . . . . . . . . 142
5.3.2 Merging Sorted Lists . . . . . . . . . . . . . . . . . . . . . . 143
5.4 The Set ADT Revisited . . . . . . . . . . . . . . . . . . . . . . . . . 147
5.4.1 A Sorted List Implementation . . . . . . . . . . . . . . . . . 147
5.4.2 Comparing the Implementations . . . . . . . . . . . . . . . 152
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

Chapter 6: Linked Structures 155


6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
6.2 The Singly Linked List . . . . . . . . . . . . . . . . . . . . . . . . . 159
6.2.1 Traversing the Nodes . . . . . . . . . . . . . . . . . . . . . 159
6.2.2 Searching for a Node . . . . . . . . . . . . . . . . . . . . . 161
6.2.3 Prepending Nodes . . . . . . . . . . . . . . . . . . . . . . . 162
6.2.4 Removing Nodes . . . . . . . . . . . . . . . . . . . . . . . . 163
6.3 The Bag ADT Revisited . . . . . . . . . . . . . . . . . . . . . . . . 165
6.3.1 A Linked List Implementation . . . . . . . . . . . . . . . . . 165
6.3.2 Comparing Implementations . . . . . . . . . . . . . . . . . 167
6.3.3 Linked List Iterators . . . . . . . . . . . . . . . . . . . . . . 168
6.4 More Ways to Build a Linked List . . . . . . . . . . . . . . . . . . . 169
6.4.1 Using a Tail Reference . . . . . . . . . . . . . . . . . . . . . 169
6.4.2 The Sorted Linked List . . . . . . . . . . . . . . . . . . . . . 171
6.5 The Sparse Matrix Revisited . . . . . . . . . . . . . . . . . . . . . 174
6.5.1 An Array of Linked Lists Implementation . . . . . . . . . . . 175
6.5.2 Comparing the Implementations . . . . . . . . . . . . . . . 178
6.6 Application: Polynomials . . . . . . . . . . . . . . . . . . . . . . . . 179
6.6.1 Polynomial Operations . . . . . . . . . . . . . . . . . . . . . 179
viii CONTENTS

6.6.2 The Polynomial ADT . . . . . . . . . . . . . . . . . . . . . . 181


6.6.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 181
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190

Chapter 7: Stacks 193


7.1 The Stack ADT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
7.2 Implementing the Stack . . . . . . . . . . . . . . . . . . . . . . . . 195
7.2.1 Using a Python List . . . . . . . . . . . . . . . . . . . . . . 195
7.2.2 Using a Linked List . . . . . . . . . . . . . . . . . . . . . . . 196
7.3 Stack Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
7.3.1 Balanced Delimiters . . . . . . . . . . . . . . . . . . . . . . 199
7.3.2 Evaluating Postfix Expressions . . . . . . . . . . . . . . . . 202
7.4 Application: Solving a Maze . . . . . . . . . . . . . . . . . . . . . . 206
7.4.1 Backtracking . . . . . . . . . . . . . . . . . . . . . . . . . . 207
7.4.2 Designing a Solution . . . . . . . . . . . . . . . . . . . . . . 208
7.4.3 The Maze ADT . . . . . . . . . . . . . . . . . . . . . . . . . 211
7.4.4 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 214
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

Chapter 8: Queues 221


8.1 The Queue ADT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
8.2 Implementing the Queue . . . . . . . . . . . . . . . . . . . . . . . . 222
8.2.1 Using a Python List . . . . . . . . . . . . . . . . . . . . . . 222
8.2.2 Using a Circular Array . . . . . . . . . . . . . . . . . . . . . 224
8.2.3 Using a Linked List . . . . . . . . . . . . . . . . . . . . . . . 228
8.3 Priority Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
8.3.1 The Priority Queue ADT . . . . . . . . . . . . . . . . . . . . 230
8.3.2 Implementation: Unbounded Priority Queue . . . . . . . . . 232
8.3.3 Implementation: Bounded Priority Queue . . . . . . . . . . 235
8.4 Application: Computer Simulations . . . . . . . . . . . . . . . . . . 237
8.4.1 Airline Ticket Counter . . . . . . . . . . . . . . . . . . . . . 237
8.4.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 239
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

Chapter 9: Advanced Linked Lists 247


9.1 The Doubly Linked List . . . . . . . . . . . . . . . . . . . . . . . . . 247
9.1.1 Organization . . . . . . . . . . . . . . . . . . . . . . . . . . 247
9.1.2 List Operations . . . . . . . . . . . . . . . . . . . . . . . . . 248
9.2 The Circular Linked List . . . . . . . . . . . . . . . . . . . . . . . . 253
CONTENTS ix

9.2.1 Organization . . . . . . . . . . . . . . . . . . . . . . . . . . 253


9.2.2 List Operations . . . . . . . . . . . . . . . . . . . . . . . . . 254
9.3 Multi-Linked Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
9.3.1 Multiple Chains . . . . . . . . . . . . . . . . . . . . . . . . . 259
9.3.2 The Sparse Matrix . . . . . . . . . . . . . . . . . . . . . . . 260
9.4 Complex Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
9.5 Application: Text Editor . . . . . . . . . . . . . . . . . . . . . . . . . 263
9.5.1 Typical Editor Operations . . . . . . . . . . . . . . . . . . . 263
9.5.2 The Edit Buffer ADT . . . . . . . . . . . . . . . . . . . . . . 266
9.5.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 268
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

Chapter 10: Recursion 277


10.1 Recursive Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 277
10.2 Properties of Recursion . . . . . . . . . . . . . . . . . . . . . . . . 279
10.2.1 Factorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
10.2.2 Recursive Call Trees . . . . . . . . . . . . . . . . . . . . . . 281
10.2.3 The Fibonacci Sequence . . . . . . . . . . . . . . . . . . . 283
10.3 How Recursion Works . . . . . . . . . . . . . . . . . . . . . . . . . 283
10.3.1 The Run Time Stack . . . . . . . . . . . . . . . . . . . . . . 284
10.3.2 Using a Software Stack . . . . . . . . . . . . . . . . . . . . 286
10.3.3 Tail Recursion . . . . . . . . . . . . . . . . . . . . . . . . . 289
10.4 Recursive Applications . . . . . . . . . . . . . . . . . . . . . . . . . 290
10.4.1 Recursive Binary Search . . . . . . . . . . . . . . . . . . . 290
10.4.2 Towers of Hanoi . . . . . . . . . . . . . . . . . . . . . . . . 292
10.4.3 Exponential Operation . . . . . . . . . . . . . . . . . . . . . 296
10.4.4 Playing Tic-Tac-Toe . . . . . . . . . . . . . . . . . . . . . . 297
10.5 Application: The Eight-Queens Problem . . . . . . . . . . . . . . . 299
10.5.1 Solving for Four-Queens . . . . . . . . . . . . . . . . . . . . 301
10.5.2 Designing a Solution . . . . . . . . . . . . . . . . . . . . . . 303
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Chapter 11: Hash Tables 309


11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
11.2 Hashing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
11.2.1 Linear Probing . . . . . . . . . . . . . . . . . . . . . . . . . 312
11.2.2 Clustering . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
11.2.3 Rehashing . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
11.2.4 Efficiency Analysis . . . . . . . . . . . . . . . . . . . . . . . 320
11.3 Separate Chaining . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
x CONTENTS

11.4 Hash Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323


11.5 The HashMap Abstract Data Type . . . . . . . . . . . . . . . . . . 325
11.6 Application: Histograms . . . . . . . . . . . . . . . . . . . . . . . . 330
11.6.1 The Histogram Abstract Data Type . . . . . . . . . . . . . . 330
11.6.2 The Color Histogram . . . . . . . . . . . . . . . . . . . . . . 334
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338

Chapter 12: Advanced Sorting 339


12.1 Merge Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
12.1.1 Algorithm Description . . . . . . . . . . . . . . . . . . . . . 340
12.1.2 Basic Implementation . . . . . . . . . . . . . . . . . . . . . 340
12.1.3 Improved Implementation . . . . . . . . . . . . . . . . . . . 342
12.1.4 Efficiency Analysis . . . . . . . . . . . . . . . . . . . . . . . 345
12.2 Quick Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
12.2.1 Algorithm Description . . . . . . . . . . . . . . . . . . . . . 348
12.2.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 349
12.2.3 Efficiency Analysis . . . . . . . . . . . . . . . . . . . . . . . 353
12.3 How Fast Can We Sort? . . . . . . . . . . . . . . . . . . . . . . . . 353
12.4 Radix Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
12.4.1 Algorithm Description . . . . . . . . . . . . . . . . . . . . . 354
12.4.2 Basic Implementation . . . . . . . . . . . . . . . . . . . . . 356
12.4.3 Efficiency Analysis . . . . . . . . . . . . . . . . . . . . . . . 358
12.5 Sorting Linked Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 358
12.5.1 Insertion Sort . . . . . . . . . . . . . . . . . . . . . . . . . . 359
12.5.2 Merge Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Chapter 13: Binary Trees 369


13.1 The Tree Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
13.2 The Binary Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
13.2.1 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
13.2.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 375
13.2.3 Tree Traversals . . . . . . . . . . . . . . . . . . . . . . . . . 376
13.3 Expression Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
13.3.1 Expression Tree Abstract Data Type . . . . . . . . . . . . . 382
13.3.2 String Representation . . . . . . . . . . . . . . . . . . . . . 383
13.3.3 Tree Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . 384
13.3.4 Tree Construction . . . . . . . . . . . . . . . . . . . . . . . 386
13.4 Heaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
13.4.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
CONTENTS xi

13.4.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 395


13.4.3 The Priority Queue Revisited . . . . . . . . . . . . . . . . . 398
13.5 Heapsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
13.5.1 Simple Implementation . . . . . . . . . . . . . . . . . . . . 400
13.5.2 Sorting In Place . . . . . . . . . . . . . . . . . . . . . . . . 400
13.6 Application: Morse Code . . . . . . . . . . . . . . . . . . . . . . . . 404
13.6.1 Decision Trees . . . . . . . . . . . . . . . . . . . . . . . . . 405
13.6.2 The ADT Definition . . . . . . . . . . . . . . . . . . . . . . . 406
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410

Chapter 14: Search Trees 411


14.1 The Binary Search Tree . . . . . . . . . . . . . . . . . . . . . . . . 412
14.1.1 Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
14.1.2 Min and Max Values . . . . . . . . . . . . . . . . . . . . . . 415
14.1.3 Insertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
14.1.4 Deletions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
14.1.5 Efficiency of Binary Search Trees . . . . . . . . . . . . . . . 425
14.2 Search Tree Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . 427
14.3 AVL Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428
14.3.1 Insertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
14.3.2 Deletions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
14.3.3 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . 435
14.4 The 2-3 Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
14.4.1 Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
14.4.2 Insertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
14.4.3 Efficiency of the 2-3 Tree . . . . . . . . . . . . . . . . . . . 449
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
Programming Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452

Appendix A: Python Review 453


A.1 The Python Interpreter . . . . . . . . . . . . . . . . . . . . . . . . . 453
A.2 The Basics of Python . . . . . . . . . . . . . . . . . . . . . . . . . 454
A.2.1 Primitive Types . . . . . . . . . . . . . . . . . . . . . . . . . 455
A.2.2 Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
A.2.3 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
A.2.4 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . 458
A.2.5 Logical Expressions . . . . . . . . . . . . . . . . . . . . . . 459
A.2.6 Using Functions and Methods . . . . . . . . . . . . . . . . 461
A.2.7 Standard Library . . . . . . . . . . . . . . . . . . . . . . . . 462
A.3 User Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
A.3.1 Standard Input . . . . . . . . . . . . . . . . . . . . . . . . . 463
xii CONTENTS

A.3.2 Standard Output . . . . . . . . . . . . . . . . . . . . . . . . 464


A.4 Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
A.4.1 Selection Constructs . . . . . . . . . . . . . . . . . . . . . . 467
A.4.2 Repetition Constructs . . . . . . . . . . . . . . . . . . . . . 469
A.5 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
A.5.1 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
A.5.2 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
A.5.3 Tuples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
A.5.4 Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
A.6 Text Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
A.6.1 File Access . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
A.6.2 Writing to Files . . . . . . . . . . . . . . . . . . . . . . . . . 478
A.6.3 Reading from Files . . . . . . . . . . . . . . . . . . . . . . . 479
A.7 User-Defined Functions . . . . . . . . . . . . . . . . . . . . . . . . 480
A.7.1 The Function Definition . . . . . . . . . . . . . . . . . . . . 480
A.7.2 Variable Scope . . . . . . . . . . . . . . . . . . . . . . . . . 483
A.7.3 Main Routine . . . . . . . . . . . . . . . . . . . . . . . . . . 483

Appendix B: User-Defined Modules 485


B.1 Structured Programs . . . . . . . . . . . . . . . . . . . . . . . . . . 485
B.2 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486

Appendix C: Exceptions 489


C.1 Catching Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . 489
C.2 Raising Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
C.3 Standard Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . 491
C.4 Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491

Appendix D: Classes 493


D.1 The Class Definition . . . . . . . . . . . . . . . . . . . . . . . . . . 493
D.1.1 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . 494
D.1.2 Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
D.1.3 Using Modules . . . . . . . . . . . . . . . . . . . . . . . . . 497
D.1.4 Hiding Attributes . . . . . . . . . . . . . . . . . . . . . . . . 498
D.2 Overloading Operators . . . . . . . . . . . . . . . . . . . . . . . . . 500
D.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
D.3.1 Deriving Child Classes . . . . . . . . . . . . . . . . . . . . . 503
D.3.2 Creating Class Instances . . . . . . . . . . . . . . . . . . . 504
D.3.3 Invoking Methods . . . . . . . . . . . . . . . . . . . . . . . 505
D.4 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
Preface

The standard second course in computer science has traditionally covered the fun-
damental data structures and algorithms, but more recently these topics have been
included in the broader topic of abstract data types. This book is no exception,
with the main focus on the design, use, and implementation of abstract data types.
The importance of designing and using abstract data types for easier modular pro-
gramming is emphasized throughout the text. The traditional data structures are
also presented throughout the text in terms of implementing the various abstract
data types. Multiple implementations using different data structures are used
throughout the text to reinforce the abstraction concept. Common algorithms are
also presented throughout the text as appropriate to provide complete coverage of
the typical data structures course.

Overview
The typical data structures course, which introduces a collection of fundamental
data structures and algorithms, can be taught using any of the different program-
ming languages available today. In recent years, more colleges have begun to adopt
the Python language for introducing students to programming and problem solv-
ing. Python provides several benefits over other languages such as C++ and Java,
the most important of which is that Python has a simple syntax that is easier to
learn. This book expands upon that use of Python by providing a Python-centric
text for the data structures course. The clean syntax and powerful features of the
language are used throughout, but the underlying mechanisms of these features
are fully explored not only to expose the “magic” but also to study their overall
efficiency.
For a number of years, many data structures textbooks have been written to
serve a dual role of introducing data structures and providing an in-depth study
of object-oriented programming (OOP). In some instances, this dual role may
compromise the original purpose of the data structures course by placing more focus
on OOP and less on the abstract data types and their underlying data structures.
To stress the importance of abstract data types, data structures, and algorithms, we
limit the discussion of OOP to the use of base classes for implementing the various
abstract data types. We do not use class inheritance or polymorphism in the main
part of the text but instead provide a basic introduction as an appendix. This
choice was made for several reasons. First, our objective is to provide a “back to

xiii
xiv PREFACE

basics” approach to learning data structures and algorithms without overwhelming


the reader with all of the OOP terminology and concepts, which is especially
important when the instructor has no plans to cover such topics. Second, different
instructors take different approaches with Python in their first course. Our aim is
to provide an excellent text to the widest possible audience. We do this by placing
the focus on the data structures and algorithms, while designing the examples to
allow the introduction of object-oriented programming if so desired.
The text also introduces the concept of algorithm analysis and explores the
efficiency of algorithms and data structures throughout the text. The major pre-
sentation of complexity analysis is contained in a single chapter, which allows it to
be omitted by instructors who do not normally cover such material in their data
structures course. Additional evaluations are provided throughout the text as new
algorithms and data structures are introduced, with the major details contained in
individual sections. When algorithm analysis is covered, examples of the various
complexity functions are introduced, including amortized cost. The latter is im-
portant when using Python since many of the list operations have a very efficient
amortized cost.

Prerequisites
This book assumes that the student has completed the standard introduction to
programming and problem-solving course using the Python language. Since the
contents of the first course can differ from college to college and instructor to
instructor, we assume the students are familiar with or can do the following:

ˆ Design and implement complete programs in Python, including the use of


modules and namespaces

ˆ Apply the basic data types and constructs, including loops, selection state-
ments, and subprograms (functions)

ˆ Create and use the built-in list and dictionary structures

ˆ Design and implement basics classes, including the use of helper methods and
private attributes

Contents and Organization


The text is organized into fourteen chapters and four appendices. The basic con-
cepts related to abstract data types, data structures, and algorithms are presented
in the first four chapters. Later chapters build on these earlier concepts to present
more advanced topics and introduce the student to additional abstract data types
and more advanced data structures. The book contains several topic threads that
run throughout the text, in which the topics are revisited in various chapters as
appropriate. The layout of the text does not force a rigid outline, but allows for the
PREFACE xv

reordering of some topics. For example, the chapters on recursion and hashing can
be presented at any time after the discussion of algorithm analysis in Chapter 4.

Chapter 1: Abstract Data Types. Introduces the concept of abstract data types
(ADTs) for both simple types, those containing individual data fields, and the more
complex types, those containing data structures. ADTs are presented in terms
of their definition, use, and implementation. After discussing the importance of
abstraction, we define several ADTs and then show how a well-defined ADT can
be used without knowing how its actually implemented. The focus then turns to
the implementation of the ADTs with an emphasis placed on the importance of
selecting an appropriate data structure. The chapter includes an introduction to
the Python iterator mechanism and provides an example of a user-defined iterator
for use with a container type ADT.

Chapter 2: Arrays. Introduces the student to the array structure, which is im-
portant since Python only provides the list structure and students are unlikely to
have seen the concept of the array as a fixed-sized structure in a first course using
Python. We define an ADT for a one-dimensional array and implement it using a
hardware array provided through a special mechanism of the C-implemented ver-
sion of Python. The two-dimensional array is also introduced and implemented
using a 1-D array of arrays. The array structures will be used throughout the text
in place of the Python’s list when it is the appropriate choice. The implementa-
tion of the list structure provided by Python is presented to show how the various
operations are implemented using a 1-D array. The Matrix ADT is introduced and
includes an implementation using a two-dimensional array that exposes the stu-
dents to an example of an ADT that is best implemented using a structure other
than the list or dictionary.

Chapter 3: Sets and Maps. This chapter reintroduces the students to both
the Set and Map (or dictionary) ADTs with which they are likely to be familiar
from their first programming course using Python. Even though Python provides
these ADTs, they both provide great examples of abstract data types that can be
implemented in many different ways. The chapter also continues the discussion of
arrays from the previous chapter by introducing multi-dimensional arrays (those
of two or more dimensions) along with the concept of physically storing these
using a one-dimensional array in either row-major or column-major order. The
chapter concludes with an example application that can benefit from the use of a
three-dimensional array.

Chapter 4: Algorithm Analysis. Introduces the basic concept and importance


of complexity analysis by evaluating the operations of Python’s list structure and
the Set ADT as implemented in the previous chapter. This information will be used
to provide a more efficient implementation of the Set ADT in the following chapter.
The chapter concludes by introducing the Sparse Matrix ADT and providing a more
efficient implementation with the use of a list in place of a two-dimensional array.
xvi PREFACE

Chapter 5: Searching and Sorting. Introduces the concepts of searching and


sorting and illustrates how the efficiency of some ADTs can be improved when
working with sorted sequences. Search operations for an unsorted sequence are
discussed and the binary search algorithm is introduced as a way of improving this
operation. Three of the basic sorting algorithms are also introduced to further
illustrate the use of algorithm analysis. A new implementation of the Set ADT is
provided to show how different data structures or data organizations can change
the efficiency of an ADT.

Chapter 6: Linked Structures. Provides an introduction to dynamic structures


by illustrating the construction and use of the singly linked list using dynamic
storage allocation. The common operations — traversal, searching, insertion, and
deletion — are presented as is the use of a tail reference when appropriate. Several
of the ADTs presented in earlier chapters are reimplemented using the singly linked
list, and the run times of their operations are compared to the earlier versions.
A new implementation of the Sparse Matrix is especially eye-opening to many
students as it uses an array of sorted linked lists instead of a single Python list as
was done in an earlier chapter.

Chapter 7: Stacks. Introduces the Stack ADT and includes implementations


using both a Python list and a linked list. Several common stack applications
are then presented, including balanced delimiter verification and the evaluation of
postfix expressions. The concept of backtracking is also introduced as part of the
application for solving a maze. A detailed discussion is provided in designing a
solution and a partial implementation.

Chapter 8: Queues. Introduces the Queue ADT and includes three different
implementations: Python list, circular array, and linked list. The priority queue
is introduced to provide an opportunity to discuss different structures and data
organization for an efficient implementation. The application of the queue presents
the concept of discrete event computer simulations using an airline ticket counter
as the example.

Chapter 9: Advanced Linked Lists. Continues the discussion of dynamic struc-


tures by introducing a collection of more advanced linked lists. These include the
doubly linked, circularly linked, and multi linked lists. The latter provides an
example of a linked structure containing multiple chains and is applied by reimple-
menting the Sparse Matrix to use two arrays of linked lists, one for the rows and
one for the columns. The doubly linked list is applied to the problem of designing
and implementing an Edit Buffer ADT for use with a basic text editor.

Chapter 10: Recursion. Introduces the use of recursion to solve various pro-
gramming problems. The properties of creating recursive functions are presented
along with common examples, including factorial, greatest common divisor, and
the Towers of Hanoi. The concept of backtracking is revisited to use recursion for
solving the eight-queens problem.
PREFACE xvii

Chapter 11: Hash Tables. Introduces the concept of hashing and the use of hash
tables for performing fast searches. Different addressing techniques are presented,
including those for both closed and open addressing. Collision resolution techniques
and hash function design are also discussed. The magic behind Python’s dictionary
structure, which uses a hash table, is exposed and its efficiency evaluated.

Chapter 12: Advanced Sorting. Continues the discussion of the sorting problem
by introducing the recursive sorting algorithms—merge sort and quick sort—along
with the radix distribution sort algorithm, all of which can be used to sort se-
quences. Some of the common techniques for sorting linked lists are also presented.

Chapter 13: Binary Trees. Presents the tree structure and the general binary
tree specifically. The construction and use of the binary tree is presented along
with various properties and the various traversal operations. The binary tree is
used to build and evaluate arithmetic expressions and in decoding Morse Code
sequences. The tree-based heap structure is also introduced along with its use in
implementing a priority queue and the heapsort algorithm.

Chapter 14: Search Trees. Continues the discussion from the previous chapter
by using the tree structure to solve the search problem. The basic binary search
tree and the balanced binary search tree (AVL) are both introduced along with
new implementations of the Map ADT. Finally, a brief introduction to the 2-3
multi-way tree is also provided, which shows an alternative to both the binary
search and AVL trees.

Appendix A: Python Review. Provides a review of the Python language and


concepts learned in the traditional first course. The review includes a presentation
of the basic constructs and built-in data structures.

Appendix B: User-Defined Modules. Describes the use of modules in creating


well structured programs. The different approaches for importing modules is also
discussed along with the use of namespaces.

Appendix C: Exceptions. Provides a basic introduction to the use of exceptions


for handling and raising errors during program execution.

Appendix D: Classes. Introduces the basic concepts of object-oriented program-


ming, including encapsulation, inheritance, and polymorphism. The presentation
is divided into two main parts. The first part presents the basic design and use
of classes for those instructors who use a “back to basics” approach in teaching
data structures. The second part briefly explores the more advanced features of
inheritance and polymorphism for those instructors who typically include these
topics in their course.
xviii PREFACE

Acknowledgments
There are a number of individuals I would like to thank for helping to make this
book possible. First, I must acknowledge two individuals who served as mentors
in the early part of my career. Mary Dayne Gregg (University of Southern Mis-
sissippi), who was the best computer science teacher I have ever known, shared
her love of teaching and provided a great role model in academia. Richard Prosl
(Professor Emeritus, College of William and Mary) served not only as my graduate
advisor but also shared great insight into teaching and helped me to become a good
teacher.
A special thanks to the many students I have taught over the years, especially
those at Washington and Lee University, who during the past five years used draft
versions of the manuscript and provided helpful suggestions. I would also like to
thank some of my colleagues who provided great advice and the encouragement
to complete the project: Sara Sprenkle (Washington and Lee University), Debbie
Noonan (College of William and Mary), and Robert Noonan (College of William
and Mary).
I am also grateful to the following individuals who served as outside review-
ers and provided valuable feedback and helpful suggestions: Esmail Bonakdarian
(Franklin University), David Dubin (University of Illinois at Urbana-Champaign)
Mark E. Fenner (Norwich University), Robert Franks (Central College), Charles J.
Leska (Randolph-Macon College), Fernando Martincic (Wayne State University),
Joseph D. Sloan (Wofford College), David A. Sykes (Wofford College), and Stan
Thomas (Wake Forest University).
Finally, I would like to thank everyone at John Wiley & Sons who helped make
this book possible. I would especially like to thank Beth Golub, Mike Berlin, and
Amy Weintraub, with whom I worked closely throughout the process and who
helped to make this first book an enjoyable experience.

Rance D. Necaise
CHAPTER 1
Abstract Data Types

The foundation of computer science is based on the study of algorithms. An al-


gorithm is a sequence of clear and precise step-by-step instructions for solving a
problem in a finite amount of time. Algorithms are implemented by translating
the step-by-step instructions into a computer program that can be executed by
a computer. This translation process is called computer programming or sim-
ply programming . Computer programs are constructed using a programming
language appropriate to the problem. While programming is an important part
of computer science, computer science is not the study of programming. Nor is
it about learning a particular programming language. Instead, programming and
programming languages are tools used by computer scientists to solve problems.

1.1 Introduction
Data items are represented within a computer as a sequence of binary digits. These
sequences can appear very similar but have different meanings since computers
can store and manipulate different types of data. For example, the binary se-
quence 01001100110010110101110011011100 could be a string of characters, an in-
teger value, or a real value. To distinguish between the different types of data, the
term type is often used to refer to a collection of values and the term data type to
refer to a given type along with a collection of operations for manipulating values
of the given type.
Programming languages commonly provide data types as part of the language
itself. These data types, known as primitives, come in two categories: simple
and complex. The simple data types consist of values that are in the most
basic form and cannot be decomposed into smaller parts. Integer and real types,
for example, consist of single numeric values. The complex data types, on the
other hand, are constructed of multiple components consisting of simple types or
other complex types. In Python, objects, strings, lists, and dictionaries, which can

1
2 CHAPTER 1 Abstract Data Types

contain multiple values, are all examples of complex types. The primitive types
provided by a language may not be sufficient for solving large complex problems.
Thus, most languages allow for the construction of additional data types, known
as user-defined types since they are defined by the programmer and not the
language. Some of these data types can themselves be very complex.

1.1.1 Abstractions
To help manage complex problems and complex data types, computer scientists
typically work with abstractions. An abstraction is a mechanism for separat-
ing the properties of an object and restricting the focus to those relevant in the
current context. The user of the abstraction does not have to understand all of
the details in order to utilize the object, but only those relevant to the current task
or problem.
Two common types of abstractions encountered in computer science are proce-
dural, or functional, abstraction and data abstraction. Procedural abstraction
is the use of a function or method knowing what it does but ignoring how it’s
accomplished. Consider the mathematical square root function which you have
probably used at some point. You know the function will compute the square root
of a given number, but do you know how the square root is computed? Does it
matter if you know how it is computed, or is simply knowing how to correctly use
the function sufficient? Data abstraction is the separation of the properties of a
data type (its values and operations) from the implementation of that data type.
You have used strings in Python many times. But do you know how they are
implemented? That is, do you know how the data is structured internally or how
the various operations are implemented?
Typically, abstractions of complex problems occur in layers, with each higher
layer adding more abstraction than the previous. Consider the problem of repre-
senting integer values on computers and performing arithmetic operations on those
values. Figure 1.1 illustrates the common levels of abstractions used with integer
arithmetic. At the lowest level is the hardware with little to no abstraction since it
includes binary representations of the values and logic circuits for performing the
arithmetic. Hardware designers would deal with integer arithmetic at this level
and be concerned with its correct implementation. A higher level of abstraction
for integer values and arithmetic is provided through assembly language, which in-
volves working with binary values and individual instructions corresponding to the
underlying hardware. Compiler writers and assembly language programmers would
work with integer arithmetic at this level and must ensure the proper selection of
assembly language instructions to compute a given mathematical expression. For
example, suppose we wish to compute x = a + b − 5. At the assembly language
level, this expression must be split into multiple instructions for loading the values
from memory, storing them into registers, and then performing each arithmetic
operation separately, as shown in the following psuedocode:

loadFromMem( R1, 'a' )


loadFromMem( R2, 'b' )
1.1 Introduction 3

add R0, R1, R2


sub R0, R0, 5
storeToMem( R0, 'x' )

To avoid this level of complexity, high-level programming languages add an-


other layer of abstraction above the assembly language level. This abstraction
is provided through a primitive data type for storing integer values and a set of
well-defined operations that can be performed on those values. By providing this
level of abstraction, programmers can work with variables storing decimal values
and specify mathematical expressions in a more familiar notation (x = a + b − 5)
than is possible with assembly language instructions. Thus, a programmer does
not need to know the assembly language instructions required to evaluate a math-
ematical expression or understand the hardware implementation in order to use
integer arithmetic in a computer program.

Software-Implemented
Software-Implemented Higher Level
Big
Big Integers
Integers

High-Level
High-Level Language
Language
Instructions
Instructions

Assembly
Assembly Language
Language
Instructions
Instructions

Hardware
Hardware Lower Level
Implementation
Implementation

Figure 1.1: Levels of abstraction used with integer arithmetic.

One problem with the integer arithmetic provided by most high-level languages
and in computer hardware is that it works with values of a limited size. On 32-bit
architecture computers, for example, signed integer values are limited to the range
−231 . . . (231 − 1). What if we need larger values? In this case, we can provide
long or “big integers” implemented in software to allow values of unlimited size.
This would involve storing the individual digits and implementing functions or
methods for performing the various arithmetic operations. The implementation
of the operations would use the primitive data types and instructions provided by
the high-level language. Software libraries that provide big integer implementations
are available for most common programming languages. Python, however, actually
provides software-implemented big integers as part of the language itself.

1.1.2 Abstract Data Types


An abstract data type (or ADT ) is a programmer-defined data type that spec-
ifies a set of data values and a collection of well-defined operations that can be
performed on those values. Abstract data types are defined independent of their
4 CHAPTER 1 Abstract Data Types

implementation, allowing us to focus on the use of the new data type instead of
how it’s implemented. This separation is typically enforced by requiring interac-
tion with the abstract data type through an interface or defined set of operations.
This is known as information hiding . By hiding the implementation details and
requiring ADTs to be accessed through an interface, we can work with an ab-
straction and focus on what functionality the ADT provides instead of how that
functionality is implemented.
Abstract data types can be viewed like black boxes as illustrated in Figure 1.2.
User programs interact with instances of the ADT by invoking one of the several
operations defined by its interface. The set of operations can be grouped into four
categories:

ˆ Constructors: Create and initialize new instances of the ADT.


ˆ Accessors: Return data contained in an instance without modifying it.
ˆ Mutators: Modify the contents of an ADT instance.
ˆ Iterators: Process individual data components sequentially.

User programs interact with


ADTs through their interface
or set of operations. string ADT
str() The implementation
User
User details are hidden
Program
Program upper() as if inside a black box.
lower()
:

Figure 1.2: Separating the ADT definition from its implementation.

The implementation of the various operations are hidden inside the black box,
the contents of which we do not have to know in order to utilize the ADT. There
are several advantages of working with abstract data types and focusing on the
“what” instead of the “how.”

ˆ We can focus on solving the problem at hand instead of getting bogged down
in the implementation details. For example, suppose we need to extract a
collection of values from a file on disk and store them for later use in our
program. If we focus on the implementation details, then we have to worry
about what type of storage structure to use, how it should be used, and
whether it is the most efficient choice.

ˆ We can reduce logical errors that can occur from accidental misuse of storage
structures and data types by preventing direct access to the implementation. If
we used a list to store the collection of values in the previous example, there
is the opportunity to accidentally modify its contents in a part of our code
1.1 Introduction 5

where it was not intended. This type of logical error can be difficult to track
down. By using ADTs and requiring access via the interface, we have fewer
access points to debug.

ˆ The implementation of the abstract data type can be changed without having
to modify the program code that uses the ADT. There are many times when
we discover the initial implementation of an ADT is not the most efficient or
we need the data organized in a different way. Suppose our initial approach
to the previous problem of storing a collection of values is to simply append
new values to the end of the list. What happens if we later decide the items
should be arranged in a different order than simply appending them to the
end? If we are accessing the list directly, then we will have to modify our code
at every point where values are added and make sure they are not rearranged
in other places. By requiring access via the interface, we can easily “swap out”
the black box with a new implementation with no impact on code segments
that use the ADT.

ˆ It’s easier to manage and divide larger programs into smaller modules, al-
lowing different members of a team to work on the separate modules. Large
programming projects are commonly developed by teams of programmers in
which the workload is divided among the members. By working with ADTs
and agreeing on their definition, the team can better ensure the individual
modules will work together when all the pieces are combined. Using our pre-
vious example, if each member of the team directly accessed the list storing
the collection of values, they may inadvertently organize the data in different
ways or modify the list in some unexpected way. When the various modules
are combined, the results may be unpredictable.

1.1.3 Data Structures


Working with abstract data types, which separate the definition from the imple-
mentation, is advantageous in solving problems and writing programs. At some
point, however, we must provide a concrete implementation in order for the pro-
gram to execute. ADTs provided in language libraries, like Python, are imple-
mented by the maintainers of the library. When you define and create your own
abstract data types, you must eventually provide an implementation. The choices
you make in implementing your ADT can affect its functionality and efficiency.
Abstract data types can be simple or complex. A simple ADT is composed
of a single or several individually named data fields such as those used to represent
a date or rational number. The complex ADTs are composed of a collection of
data values such as the Python list or dictionary. Complex abstract data types
are implemented using a particular data structure, which is the physical rep-
resentation of how data is organized and manipulated. Data structures can be
characterized by how they store and organize the individual data elements and
what operations are available for accessing and manipulating the data.
6 CHAPTER 1 Abstract Data Types

There are many common data structures, including arrays, linked lists, stacks,
queues, and trees, to name a few. All data structures store a collection of values,
but differ in how they organize the individual data items and by what operations
can be applied to manage the collection. The choice of a particular data structure
depends on the ADT and the problem at hand. Some data structures are better
suited to particular problems. For example, the queue structure is perfect for
implementing a printer queue, while the B-Tree is the better choice for a database
index. No matter which data structure we use to implement an ADT, by keeping
the implementation separate from the definition, we can use an abstract data type
within our program and later change to a different implementation, as needed,
without having to modify our existing code.

1.1.4 General Definitions


There are many different terms used in computer science. Some of these can have
different meanings among the various textbooks and programming languages. To
aide the reader and to avoid confusion, we define some of the common terms we
will be using throughout the text.
A collection is a group of values with no implied organization or relationship
between the individual values. Sometimes we may restrict the elements to a specific
data type such as a collection of integers or floating-point values.
A container is any data structure or abstract data type that stores and orga-
nizes a collection. The individual values of the collection are known as elements
of the container and a container with no elements is said to be empty . The orga-
nization or arrangement of the elements can vary from one container to the next as
can the operations available for accessing the elements. Python provides a number
of built-in containers, which include strings, tuples, lists, dictionaries, and sets.
A sequence is a container in which the elements are arranged in linear order
from front to back, with each element accessible by position. Throughout the text,
we assume that access to the individual elements based on their position within
the linear order is provided using the subscript operator. Python provides two
immutable sequences, strings and tuples, and one mutable sequence, the list. In
the next chapter, we introduce the array structure, which is also a commonly used
mutable sequence.
A sorted sequence is one in which the position of the elements is based on
a prescribed relationship between each element and its successor. For example,
we can create a sorted sequence of integers in which the elements are arranged in
ascending or increasing order from smallest to largest value.
In computer science, the term list is commonly used to refer to any collection
with a linear ordering. The ordering is such that every element in the collection,
except the first one, has a unique predecessor and every element, except the last
one, has a unique successor. By this definition, a sequence is a list, but a list is
not necessarily a sequence since there is no requirement that a list provide access
to the elements by position. Python, unfortunately, uses the same name for its
built-in mutable sequence type, which in other languages would be called an array
1.2 The Date Abstract Data Type 7

list or vector abstract data type. To avoid confusion, we will use the term list to
refer to the data type provided by Python and use the terms general list or list
structure when referring to the more general list structure as defined earlier.

1.2 The Date Abstract Data Type


An abstract data type is defined by specifying the domain of the data elements
that compose the ADT and the set of operations that can be performed on that
domain. The definition should provide a clear description of the ADT including
both its domain and each of its operations as only those operations specified can be
performed on an instance of the ADT. Next, we provide the definition of a simple
abstract data type for representing a date in the proleptic Gregorian calendar.

1.2.1 Defining the ADT


The Gregorian calendar was introduced in the year 1582 by Pope Gregory XIII to
replace the Julian calendar. The new calendar corrected for the miscalculation of
the lunar year and introduced the leap year. The official first date of the Gregorian
calendar is Friday, October 15, 1582. The proleptic Gregorian calendar is an
extension for accommodating earlier dates with the first date on November 24,
4713 BC. This extension simplifies the handling of dates across older calendars
and its use can be found in many software applications.

Define Date ADT

A date represents a single day in the proleptic Gregorian calendar in which the
first day starts on November 24, 4713 BC.
 Date( month, day, year ): Creates a new Date instance initialized to the
given Gregorian date which must be valid. Year 1 BC and earlier are indicated
by negative year components.
 day(): Returns the Gregorian day number of this date.
 month(): Returns the Gregorian month number of this date.
 year(): Returns the Gregorian year of this date.
 monthName(): Returns the Gregorian month name of this date.
 dayOfWeek(): Returns the day of the week as a number between 0 and 6 with
0 representing Monday and 6 representing Sunday.
 numDays( otherDate ): Returns the number of days as a positive integer be-
tween this date and the otherDate.
 isLeapYear(): Determines if this date falls in a leap year and returns the
appropriate boolean value.
8 CHAPTER 1 Abstract Data Types

 advanceBy( days ): Advances the date by the given number of days. The date
is incremented if days is positive and decremented if days is negative. The
date is capped to November 24, 4714 BC, if necessary.
 comparable ( otherDate ): Compares this date to the otherDate to deter-
mine their logical ordering. This comparison can be done using any of the
logical operators <, <=, >, >=, ==, !=.
 toString (): Returns a string representing the Gregorian date in the format
mm/dd/yyyy. Implemented as the Python operator that is automatically called
via the str() constructor.

The abstract data types defined in the text will be implemented as Python
classes. When defining an ADT, we specify the ADT operations as method pro-
totypes. The class constructor, which is used to create an instance of the ADT, is
indicated by the name of the class used in the implementation.
Python allows classes to define or overload various operators that can be used
more naturally in a program without having to call a method by name. We define
all ADT operations as named methods, but implement some of them as operators
when appropriate instead of using the named method. The ADT operations that
will be implemented as Python operators are indicated in italicized text and a brief
comment is provided in the ADT definition indicating the corresponding operator.
This approach allows us to focus on the general ADT specification that can be
easily translated to other languages if the need arises but also allows us to take
advantage of Python’s simple syntax in various sample programs.

1.2.2 Using the ADT


To illustrate the use of the Date ADT, consider the program in Listing 1.1, which
processes a collection of birth dates. The dates are extracted from standard input
and examined. Those dates that indicate the individual is at least 21 years of age
based on a target date are printed to standard output. The user is continuously
prompted to enter a birth date until zero is entered for the month.
This simple example illustrates an advantage of working with an abstraction
by focusing on what functionality the ADT provides instead of how that function-
ality is implemented. By hiding the implementation details, we can use an ADT
independent of its implementation. In fact, the choice of implementation for the
Date ADT will have no effect on the instructions in our example program.

Class Definitions. Classes are the foundation of object-oriented


i
NOTE

programing languages and they provide a convenient mechanism for


defining and implementing abstract data types. A review of Python classes
is provided in Appendix D.
1.2 The Date Abstract Data Type 9

Listing 1.1 The checkdates.py program.

1 # Extracts a collection of birth dates from the user and determines


2 # if each individual is at least 21 years of age.
3 from date import Date
4
5 def main():
6 # Date before which a person must have been born to be 21 or older.
7 bornBefore = Date(6, 1, 1988)
8
9 # Extract birth dates from the user and determine if 21 or older.
10 date = promptAndExtractDate()
11 while date is not None :
12 if date <= bornBefore :
13 print( "Is at least 21 years of age: ", date )
14 date = promptAndExtractDate()
15
16 # Prompts for and extracts the Gregorian date components. Returns a
17 # Date object or None when the user has finished entering dates.
18 def promptAndExtractDate():
19 print( "Enter a birth date." )
20 month = int( input("month (0 to quit): ") )
21 if month == 0 :
22 return None
23 else :
24 day = int( input("day: ") )
25 year = int( input("year: ") )
26 return Date( month, day, year )
27
28 # Call the main routine.
29 main()

1.2.3 Preconditions and Postconditions


In defining the operations, we must include a specification of required inputs and
the resulting output, if any. In addition, we must specify the preconditions and
postconditions for each operation. A precondition indicates the condition or
state of the ADT instance and inputs before the operation can be performed. A
postcondition indicates the result or ending state of the ADT instance after the
operation is performed. The precondition is assumed to be true while the postcon-
dition is a guarantee as long as the preconditions are met. Attempting to perform
an operation in which the precondition is not satisfied should be flagged as an er-
ror. Consider the use of the pop(i) method for removing a value from a list. When
this method is called, the precondition states the supplied index must be within
the legal range. Upon successful completion of the operation, the postcondition
guarantees the item has been removed from the list. If an invalid index, one that
is out of the legal range, is passed to the pop() method, an exception is raised.
All operations have at least one precondition, which is that the ADT instance
has to have been previously initialized. In an object-oriented language, this pre-
condition is automatically verified since an object must be created and initialized
10 CHAPTER 1 Abstract Data Types

via the constructor before any operation can be used. Other than the initialization
requirement, an operation may not have any other preconditions. It all depends
on the type of ADT and the respective operation. Likewise, some operations may
not have a postcondition, as is the case for simple access methods, which simply
return a value without modifying the ADT instance itself. Throughout the text,
we do not explicitly state the precondition and postcondition as such, but they are
easily identified from the description of the ADT operations.
When implementing abstract data types, it’s important that we ensure the
proper execution of the various operations by verifying any stated preconditions.
The appropriate mechanism when testing preconditions for abstract data types is
to test the precondition and raise an exception when the precondition fails. You
then allow the user of the ADT to decide how they wish to handle the error, either
catch it or allow the program to abort.
Python, like many other object-oriented programming languages, raises an ex-
ception when an error occurs. An exception is an event that can be triggered
and optionally handled during program execution. When an exception is raised
indicating an error, the program can contain code to catch and gracefully handle
the exception; otherwise, the program will abort. Python also provides the assert
statement, which can be used to raise an AssertionError exception. The assert
statement is used to state what we assume to be true at a given point in the pro-
gram. If the assertion fails, Python automatically raises an AssertionError and
aborts the program, unless the exception is caught.
Throughout the text, we use the assert statement to test the preconditions
when implementing abstract data types. This allows us to focus on the implemen-
tation of the ADTs instead of having to spend time selecting the proper exception
to raise or creating new exceptions for use with our ADTs. For more information
on exceptions and assertions, refer to Appendix C.

1.2.4 Implementing the ADT


After defining the ADT, we need to provide an implementation in an appropriate
language. In our case, we will always use Python and class definitions, but any
programming language could be used. A partial implementation of the Date class is
provided in Listing 1.2, with the implementation of some methods left as exercises.

Date Representations
There are two common approaches to storing a date in an object. One approach
stores the three components—month, day, and year—as three separate fields. With
this format, it is easy to access the individual components, but it’s difficult to
compare two dates or to compute the number of days between two dates since the
number of days in a month varies from month to month. The second approach
stores the date as an integer value representing the Julian day, which is the number
of days elapsed since the initial date of November 24, 4713 BC (using the Gregorian
calendar notation). Given a Julian day number, we can compute any of the three
Gregorian components and simply subtract the two integer values to determine
1.2 The Date Abstract Data Type 11

which occurs first or how many days separate the two dates. We are going to use
the latter approach as it is very common for storing dates in computer applications
and provides for an easy implementation.

Listing 1.2 Partial implementation of the date.py module.

1 # Implements a proleptic Gregorian calendar date as a Julian day number.


2
3 class Date :
4 # Creates an object instance for the specified Gregorian date.
5 def __init__( self, month, day, year ):
6 self._julianDay = 0
7 assert self._isValidGregorian( month, day, year ), \
8 "Invalid Gregorian date."
9
10 # The first line of the equation, T = (M - 14) / 12, has to be changed
11 # since Python's implementation of integer division is not the same
12 # as the mathematical definition.
13 tmp = 0
14 if month < 3 :
15 tmp = -1
16 self._julianDay = day - 32075 + \
17 (1461 * (year + 4800 + tmp) // 4) + \
18 (367 * (month - 2 - tmp * 12) // 12) - \
19 (3 * ((year + 4900 + tmp) // 100) // 4)
20
21 # Extracts the appropriate Gregorian date component.
22 def month( self ):
23 return (self._toGregorian())[0] # returning M from (M, d, y)
24
25 def day( self ):
26 return (self._toGregorian())[1] # returning D from (m, D, y)
27
28 def year( self ):
29 return (self._toGregorian())[2] # returning Y from (m, d, Y)
30
31 # Returns day of the week as an int between 0 (Mon) and 6 (Sun).
32 def dayOfWeek( self ):
33 month, day, year = self._toGregorian()
34 if month < 3 :
35 month = month + 12
36 year = year - 1
37 return ((13 * month + 3) // 5 + day + \
38 year + year // 4 - year // 100 + year // 400) % 7
39
40 # Returns the date as a string in Gregorian format.
41 def __str__( self ):
42 month, day, year = self._toGregorian()
43 return "%02d/%02d/%04d" % (month, day, year)
44
45 # Logically compares the two dates.
46 def __eq__( self, otherDate ):
47 return self._julianDay == otherDate._julianDay
48
(Listing Continued)
12 CHAPTER 1 Abstract Data Types

Listing 1.2 Continued . . .


49 def __lt__( self, otherDate ):
50 return self._julianDay < otherDate._julianDay
51
52 def __le__( self, otherDate ):
53 return self._julianDay <= otherDate._julianDay
54
55 # The remaining methods are to be included at this point.
56 # ......
57
58 # Returns the Gregorian date as a tuple: (month, day, year).
59 def _toGregorian( self ):
60 A = self._julianDay + 68569
61 B = 4 * A // 146097
62 A = A - (146097 * B + 3) // 4
63 year = 4000 * (A + 1) // 1461001
64 A = A - (1461 * year // 4) + 31
65 month = 80 * A // 2447
66 day = A - (2447 * month // 80)
67 A = month // 11
68 month = month + 2 - (12 * A)
69 year = 100 * (B - 49) + year + A
70 return month, day, year

Constructing the Date


We begin our discussion of the implementation with the constructor, which is shown
in lines 5–19 of Listing 1.2. The Date ADT will need only a single attribute to store
the Julian day representing the given Gregorian date. To convert a Gregorian date
to a Julian day number, we use the following formula1 where day 0 corresponds to
November 24, 4713 BC and all operations involve integer arithmetic.

T = (M - 14) / 12
jday = D - 32075 + (1461 * (Y + 4800 + T) / 4) +
(367 * (M - 2 - T * 12) / 12) -
(3 * ((Y + 4900 + T) / 100) / 4)

Before attempting to convert the Gregorian date to a Julian day, we need


to verify it’s a valid date. This is necessary since the precondition states the
supplied Gregorian date must be valid. The isValidGregorian() helper method
is used to verify the validity of the given Gregorian date. This helper method,
the implementation of which is left as an exercise, tests the supplied Gregorian
date components and returns the appropriate boolean value. If a valid date is
supplied to the constructor, it is converted to the equivalent Julian day using the
equation provided earlier. Note the statements in lines 13–15. The equation for
converting a Gregorian date to a Julian day number uses integer arithmetic, but
1
Seidelmann, P. Kenneth (ed.) (1992). Explanatory Supplement to the Astronomical Almanac,
Chapter 12, pp. 604—606, University Science Books.
1.2 The Date Abstract Data Type 13

Comments. Class definitions and methods should be properly com-


i mented to aide the user in knowing what the class and/or methods do.

NOTE
To conserve space, however, classes and methods presented in this book
do not routinely include these comments since the surrounding text provides
a full explanation.

the equation line T = (M - 14) / 12 produces an incorrect result in Python due to


its implementation of integer division, which is not the same as the mathematical
definition. By definition, the result of the integer division -11/12 is 0, but Python
computes this as b−11/12.0c resulting in -1. Thus, we had to modify the first line
of the equation to produce the correct Julian day when the month component is
greater than 2.

Protected Attributes and Methods. Python does not provide a tech-


!
CAUTION

nique to protect attributes and helper methods in order to prevent their


use outside the class definition. In this text, we use identifier names, which
begin with a single underscore to flag those attributes and methods that
should be considered protected and rely on the user of the class to not at-
tempt a direct access.

The Gregorian Date


To access the Gregorian date components the Julian day must be converted back
to Gregorian. This conversion is needed in several of the ADT operations. Instead
of duplicating the formula each time it’s needed, we create a helper method to
handle the conversion as illustrated in lines 59–70 of Listing 1.2.
The toGregorian() method returns a tuple containing the day, month, and
year components. As with the conversion from Gregorian to Julian, integer arith-
metic operations are used throughout the conversion formula. By returning a tuple,
we can call the helper method and use the appropriate component from the tuple
for the given Gregorian component access method, as illustrated in lines 22–29.
The dayOfWeek() method, shown in lines 32–38, also uses the toGregorian()
conversion helper method. We determine the day of the week based on the Gre-
gorian components using a simple formula that returns an integer value between 0
and 6, where 0 represents Monday, 1 represents Tuesday, and so on.
The toString operation defined by the ADT is implemented in lines 41–43 by
overloading Python’s str method. It creates a string representation of a date in
Gregorian format. This can be done using the string format operator and supplying
the values returned from the conversion helper method. By using Python’s str
method, Python automatically calls this method on the object when you attempt
to print or convert an object to a string as in the following example:
14 CHAPTER 1 Abstract Data Types

firstDay = Date( 9, 1, 2006 )


print( firstDay )

Comparing Date Objects


We can logically compare two Date instances to determine their calendar order.
When using a Julian day to represent the dates, the date comparison is as simple
as comparing the two integer values and returning the appropriate boolean value
based on the result of that comparison. The “comparable” ADT operation is
implemented using Python’s logical comparison operators as shown in lines 46–53
of Listing 1.2. By implementing the methods for the logical comparison operators,
instances of the class become comparable objects. That is, the objects can be
compared against each other to produce a logical ordering.
You will notice that we implemented only three of the logical comparison op-
erators. The reason for this is that starting with Python version 3, Python will
automatically swap the operands and call the appropriate reflective method when
necessary. For example, if we use the expression a > b with Date objects in our
program, Python will automatically swap the operands and call b < a instead since
the lt method is defined but not gt . It will do the same for a >= b and
a <= b. When testing for equality, Python will automatically invert the result
when only one of the equality operators (== or !=) is defined. Thus, we need only
define one operator from each of the following pairs to achieve the full range of
logical comparisons: < or >, <= or >=, and == or !=. For more information on
overloading operators, refer to Appendix D.

Overloading Operators. User-defined classes can implement meth-


ods to define many of the standard Python operators such as +, *, %,
and ==, as well as the standard named operators such as in and not in.
TIP

This allows for a more natural use of the objects instead of having to call
specific named methods. It can be tempting to define operators for every
class you create, but you should limit the definition of operator methods for
classes where the specific operator has a meaningful purpose.

1.3 Bags
The Date ADT provided an example of a simple abstract data type. To illustrate
the design and implementation of a complex abstract data type, we define the Bag
ADT. A bag is a simple container like a shopping bag that can be used to store a
collection of items. The bag container restricts access to the individual items by
only defining operations for adding and removing individual items, for determining
if an item is in the bag, and for traversing over the collection of items.
1.3 Bags 15

1.3.1 The Bag Abstract Data Type


There are several variations of the Bag ADT with the one described here being a
simple bag. A grab bag is similar to the simple bag but the items are removed
from the bag at random. Another common variation is the counting bag, which
includes an operation that returns the number of occurrences in the bag of a given
item. Implementations of the grab bag and counting bag are left as exercises.

Define Bag ADT

A bag is a container that stores a collection in which duplicate values are allowed.
The items, each of which is individually stored, have no particular order but they
must be comparable.
 Bag(): Creates a bag that is initially empty.

 length (): Returns the number of items stored in the bag. Accessed using
the len() function.

 contains ( item ): Determines if the given target item is stored in the bag
and returns the appropriate boolean value. Accessed using the in operator.

 add( item ): Adds the given item to the bag.

 remove( item ): Removes and returns an occurrence of item from the bag.
An exception is raised if the element is not in the bag.

 iterator (): Creates and returns an iterator that can be used to iterate over
the collection of items.

You may have noticed our definition of the Bag ADT does not include an
operation to convert the container to a string. We could include such an operation,
but creating a string for a large collection is time consuming and requires a large
amount of memory. Such an operation can be beneficial when debugging a program
that uses an instance of the Bag ADT. Thus, it’s not uncommon to include the
str operator method for debugging purposes, but it would not typically be used
in production software. We will usually omit the inclusion of a str operator
method in the definition of our abstract data types, except in those cases where it’s
meaningful, but you may want to include one temporarily for debugging purposes.

Examples
Given the abstract definition of the Bag ADT, we can create and use a bag without
knowing how it is actually implemented. Consider the following simple example,
which creates a bag and asks the user to guess one of the values it contains.
16 CHAPTER 1 Abstract Data Types

myBag = Bag()
myBag.add( 19 )
myBag.add( 74 )
myBag.add( 23 )
myBag.add( 19 )
myBag.add( 12 )

value = int( input("Guess a value contained in the bag.") )


if value in myBag:
print( "The bag contains the value", value )
else :
print( "The bag does not contain the value", value )

Next, consider the checkdates.py sample program from the previous section
where we extracted birth dates from the user and determined which ones were
for individuals who were at least 21 years of age. Suppose we want to keep the
collection of birth dates for later use. It wouldn’t make sense to require the user to
re-enter the dates multiple times. Instead, we can store the birth dates in a bag as
they are entered and access them later, as many times as needed. The Bag ADT
is a perfect container for storing objects when the position or order of a specific
item does not matter. The following is a new version of the main routine for our
birth date checking program from Listing 1.1:

#pgm: checkdates2.py (modified main() from checkdates.py)


from linearbag import Bag
from date import Date

def main():
bornBefore = Date( 6, 1, 1988 )
bag = Bag()

# Extract dates from the user and place them in the bag.
date = promptAndExtractDate()
while date is not None :
bag.add( date )
date = promptAndExtractDate()

# Iterate over the bag and check the age.


for date in bag :
if date <= bornBefore :
print( "Is at least 21 years of age: ", date )

Why a Bag ADT?


You may be wondering, why do we need the Bag ADT when we could simply
use the list to store the items? For a small program and a small collection of
data, using a list would be appropriate. When working with large programs and
multiple team members, however, abstract data types provide several advantages
as described earlier in Section 1.1.2. By working with the abstraction of a bag,
we can: a) focus on solving the problem at hand instead of worrying about the
1.3 Bags 17

implementation of the container, b) reduce the chance of introducing errors from


misuse of the list since it provides additional operations that are not appropriate
for a bag, c) provide better coordination between different modules and designers,
and d) easily swap out our current implementation of the Bag ADT for a different,
possibly more efficient, version later.

1.3.2 Selecting a Data Structure


The implementation of a complex abstract data type typically requires the use of
a data structure for organizing and managing the collection of data items. There
are many different structures from which to choose. So how do we know which to
use? We have to evaluate the suitability of a data structure for implementing a
given abstract data type, which we base on the following criteria:

1. Does the data structure provide for the storage requirements as specified by
the domain of the ADT? Abstract data types are defined to work with a
specific domain of data values. The data structure we choose must be capable
of storing all possible values in that domain, taking into consideration any
restrictions or limitations placed on the individual items.

2. Does the data structure provide the necessary data access and manipulation
functionality to fully implement the ADT? The functionality of an abstract
data type is provided through its defined set of operations. The data structure
must allow for a full and correct implementation of the ADT without having
to violate the abstraction principle by exposing the implementation details to
the user.

3. Does the data structure lend itself to an efficient implementation of the oper-
ations? An important goal in the implementation of an abstract data type is
to provide an efficient solution. Some data structures allow for a more effi-
cient implementation than others, but not every data structure is suitable for
implementing every ADT. Efficiency considerations can help to select the best
structure from among multiple candidates.

There may be multiple data structures suitable for implementing a given ab-
stract data type, but we attempt to select the best possible based on the context
in which the ADT will be used. To accommodate different contexts, language
libraries will commonly provide several implementations of some ADTs, allowing
the programmer to choose the most appropriate. Following this approach, we in-
troduce a number of abstract data types throughout the text and present multiple
implementations as new data structures are introduced.
The efficiency of an implementation is based on complexity analysis, which is
not introduced until later in Chapter 3. Thus, we postpone consideration of the
efficiency of an implementation in selecting a data structure until that time. In
the meantime, we only consider the suitability of a data structure based on the
storage and functional requirements of the abstract data type.
18 CHAPTER 1 Abstract Data Types

We now turn our attention to selecting a data structure for implementing the
Bag ADT. The possible candidates at this point include the list and dictionary
structures. The list can store any type of comparable object, including duplicates.
Each item is stored individually, including duplicates, which means the reference
to each individual object is stored and later accessible when needed. This satisfies
the storage requirements of the Bag ADT, making the list a candidate structure
for its implementation.
The dictionary stores key/value pairs in which the key component must be
comparable and unique. To use the dictionary in implementing the Bag ADT, we
must have a way to store duplicate items as required by the definition of the ab-
stract data type. To accomplish this, each unique item can be stored in the key
part of the key/value pair and a counter can be stored in the value part. The
counter would be used to indicate the number of occurrences of the corresponding
item in the bag. When a duplicate item is added, the counter is incremented; when
a duplicate is removed, the counter is decremented.
Both the list and dictionary structures could be used to implement the Bag
ADT. For the simple version of the bag, however, the list is a better choice since
the dictionary would require twice as much space to store the contents of the bag
in the case where most of the items are unique. The dictionary is an excellent
choice for the implementation of the counting bag variation of the ADT.
Having chosen the list, we must ensure it provides the means to implement the
complete set of bag operations. When implementing an ADT, we must use the
functionality provided by the underlying data structure. Sometimes, an ADT op-
eration is identical to one already provided by the data structure. In this case, the
implementation can be quite simple and may consist of a single call to the corre-
sponding operation of the structure, while in other cases, we have to use multiple
operations provided by the structure. To help verify a correct implementation
of the Bag ADT using the list, we can outline how each bag operation will be
implemented:

ˆ An empty bag can be represented by an empty list.


ˆ The size of the bag can be determined by the size of the list.
ˆ Determining if the bag contains a specific item can be done using the equivalent
list operation.
ˆ When a new item is added to the bag, it can be appended to the end of the
list since there is no specific ordering of the items in a bag.
ˆ Removing an item from the bag can also be handled by the equivalent list
operation.
ˆ The items in a list can be traversed using a for loop and Python provides for
user-defined iterators that be used with a bag.

From this itemized list, we see that each Bag ADT operation can be imple-
mented using the available functionality of the list. Thus, the list is suitable for
implementing the bag.
1.3 Bags 19

1.3.3 List-Based Implementation


The implementation of the Bag ADT using a list is shown in Listing 1.3. The
constructor defines a single data field, which is initialized to an empty list. This
corresponds to the definition of the constructor for the Bag ADT in which the
container is initially created empty. A sample instance of the Bag class created from
the example checkdates2.py program provided earlier is illustrated in Figure 1.3.

Listing 1.3 The linearbag.py module.

1 # Implements the Bag ADT container using a Python list.


2 class Bag :
3 # Constructs an empty bag.
4 def __init__( self ):
5 self._theItems = list()
6
7 # Returns the number of items in the bag.
8 def __len__( self ):
9 return len( self._theItems )
10
11 # Determines if an item is contained in the bag.
12 def __contains__( self, item ):
13 return item in self._theItems
14
15 # Adds a new item to the bag.
16 def add( self, item ):
17 self._theItems.append( item )
18
19 # Removes and returns an instance of the item from the bag.
20 def remove( self, item ):
21 assert item in self._theItems, "The item must be in the bag."
22 ndx = self._theItems.index( item )
23 return self._theItems.pop( ndx )
24
25 # Returns an iterator for traversing the list of items.
26 def __iter__( self, item ):
27 ......

Most of the implementation details follow the specifics discussed in the previous
section. There are some additional details, however. First, the ADT definition
of the remove() operation specifies the precondition that the item must exist
in the bag in order to be removed. Thus, we must first assert that condition
and verify the existence of the item. Second, we need to provide an iteration
mechanism that allows us to iterate over the individual items in the bag. We delay

theItems  19
19 74
74 23
23 19
19 12
12

Bag 0 1 2 3 4

Figure 1.3: Sample instance of the Bag class implemented using a list.
20 CHAPTER 1 Abstract Data Types

the implementation of this operation until the next section where we discuss the
creation and use of iterators in Python.
A list stores references to objects and technically would be illustrated as shown
in the figure to the right. To conserve space and reduce the clutter that can result
in some figures, however, we illustrate objects in the text as boxes with rounded
edges and show them stored directly Bag 0 1 2 3 4
within the list structure. Variables theItems      
will be illustrated as square boxes
with a bullet in the middle and the Bag
name of the variable printed nearby. 19
19 74 74 23
23 1919 1212
Bag

1.4 Iterators
Traversals are very common operations, especially on containers. A traversal iter-
ates over the entire collection, providing access to each individual element. Traver-
sals can be used for a number of operations, including searching for a specific item
or printing an entire collection.
Python’s container types—strings, tuples, lists, and dictionaries—can be tra-
versed using the for loop construct. For our user-defined abstract data types, we
can add methods that perform specific traversal operations when necessary. For
example, if we wanted to save every item contained in a bag to a text file, we could
add a saveElements() method that traverses over the vector and writes each value
to a file. But this would limit the format of the resulting text file to that specified
in the new method. In addition to saving the items, perhaps we would like to
simply print the items to the screen in a specific way. To perform the latter, we
would have to add yet another operation to our ADT.
Not all abstract data types should provide a traversal operation, but it is appro-
priate for most container types. Thus, we need a way to allow generic traversals to
be performed. One way would be to provide the user with access to the underlying
data structure used to implement the ADT. But this would violate the abstraction
principle and defeat the purpose of defining new abstract data types.
Python, like many of today’s object-oriented languages, provides a built-in it-
erator construct that can be used to perform traversals on user-defined ADTs. An
iterator is an object that provides a mechanism for performing generic traversals
through a container without having to expose the underlying implementation. Iter-
ators are used with Python’s for loop construct to provide a traversal mechanism
for both built-in and user-defined containers. Consider the code segment from the
checkdates2.py program in Section 1.3 that uses the for loop to traverse the
collection of dates:

# Iterate over the bag and check the ages.


for date in bag :
if date <= bornBefore :
print( "Is at least 21 years of age: ", date )
1.4 Iterators 21

1.4.1 Designing an Iterator


To use Python’s traversal mechanism with our own abstract data types, we must
define an iterator class, which is a class in Python containing two special methods,
iter and next . Iterator classes are commonly defined in the same module
as the corresponding container class.
The implementation of the BagIterator class is shown in Listing 1.4. The
constructor defines two data fields. One is an alias to the list used to store the
items in the bag, and the other is a loop index variable that will be used to iterate
over that list. The loop variable is initialized to zero in order to start from the
beginning of the list. The iter method simply returns a reference to the object
itself and is always implemented to do so.

Listing 1.4 The BagIterator class, which is part of the linearbag.py module.

1 # An iterator for the Bag ADT implemented as a Python list.


2 class _BagIterator :
3 def __init__( self, theList ):
4 self._bagItems = theList
5 self._curItem = 0
6
7 def __iter__( self ):
8 return self
9
10 def __next__( self ):
11 if self._curItem < len( self._bagItems ) :
12 item = self._bagItems[ self._curItem ]
13 self._curItem += 1
14 return item
15 else :
16 raise StopIteration

The next method is called to return the next item in the container. The
method first saves a reference to the current item indicated by the loop variable.
The loop variable is then incremented by one to prepare it for the next invocation
of the next method. If there are no additional items, the method must raise a
StopIteration exception that flags the for loop to terminate. Finally, we must
add an iter method to our Bag class, as shown here:

def __iter__( self ):


return _BagIterator( self._theItems )

This method, which is responsible for creating and returning an instance of the
BagIterator class, is automatically called at the beginning of the for loop to
create an iterator object for use with the loop construct.
22 CHAPTER 1 Abstract Data Types

1.4.2 Using Iterators


With the definition of the BagIterator class and the modifications to the Bag
class, we can now use Python’s for loop with a Bag instance. When the for loop
for item in bag :
print( item )

is executed, Python automatically calls the iter method on the bag object
to create an iterator object. Figure 1.4 illustrates the state of the BagIterator
object immediately after being created. Notice the bagItems field of the iterator
object references theItems field of the bag object. This reference was assigned
by the constructor when the BagIterator object was created.

bagVectorcurItem
curItem
 0000

_BagIterator

theItems  19
19 74
74 23
23 19
19 12
12

Bag 0 1 2 3 4

Figure 1.4: The Bag and BagIterator objects before the first loop iteration.

The for loop then automatically calls the next method on the iterator
object to access the next item in the container. The state of the iterator object
changes with the curItem field having been incremented by one. This process
continues until a StopIteration exception is raised by the next method when
the items have been exhausted as indicated by the curItem. After all of the items
have been processed, the iteration is terminated and execution continues with the
next statement following the loop. The following code segment illustrates how
Python actually performs the iteration when a for loop is used with an instance
of the Bag class:
# Create a BagIterator object for myBag.
iterator = myBag.__iter__()

# Repeat the while loop until break is called.


while True :
try:
# Get the next item from the bag. If there are no
# more items, the StopIteration exception is raised.
item = iterator.__next__()
# Perform the body of the for loop.
print( item )

# Catch the exception and break from the loop when we are done.
except StopIteration:
break
1.5 Application: Student Records 23

1.5 Application: Student Records


Most computer applications are written to process and manipulate data that is
stored external to the program. Data is commonly extracted from files stored on
disk, from databases, and even from remote sites through web services. For exam-
ple, suppose we have a collection of records stored on disk that contain information
related to students at Smalltown College. We have been assigned the task to ex-
tract this information and produce a report similar to the following in which the
records are sorted by identification number.

LIST OF STUDENTS

ID NAME CLASS GPA


----- ------------------------- ---------- ----
10015 Smith, John Sophomore 3.01
10167 Jones, Wendy Junior 2.85
10175 Smith, Jane Senior 3.92
10188 Wales, Sam Senior 3.25
10200 Roberts, Sally Freshman 4.00
10208 Green, Patrick Freshman 3.95
10226 Nelson, Amy Sophomore 2.95
10334 Roberts, Jane Senior 3.81
10387 Taylor, Susan Sophomore 2.15
10400 Logan, Mark Junior 3.33
10485 Brown, Jessica Sophomore 2.91
--------------------------------------------------
Number of students: 11

Our contact in the Registrar’s office, who assigned the task, has provided some
information about the data. We know each record contains five pieces of infor-
mation for an individual student: (1) the student’s id number represented as an
integer; (2) their first and last names, which are strings; (3) an integer classification
code in the range [1 . . . 4] that indicates if the student is a freshman, sophomore,
junior, or senior; and (4) their current grade point average represented as a floating-
point value. What we have not been told, however, is how the data is stored on
disk. It could be stored in a plain text file, in a binary file, or even in a database.
In addition, if the data is stored in a text or binary file, we will need to know how
the data is formatted in the file, and if it’s in a relational database, we will need
to know the type and the structure of the database.

1.5.1 Designing a Solution


Even though we have not yet been told the type of file or the format used to store
the data, we can begin designing and implementing a solution by working with
an abstraction of the input source. No matter the source or format of the data,
the extraction of data records from external storage requires similar steps: open
a connection, extract the individual records, then close the connection. To aide
in our effort, we define a Student File Reader ADT to represent the extraction of
24 CHAPTER 1 Abstract Data Types

data from an external file or database. In computer programming, an object used


to input data into a program is sometimes referred to as a reader while an object
used to output data is referred to as a writer .

Define Student File Reader ADT

A student file reader is used to extract student records from external storage. The
five data components of the individual records are extracted and stored in a storage
object specific for this collection of student records.
 StudentFileReader( filename ): Creates a student reader instance for ex-
tracting student records from the given file. The type and format of the file
is dependent on the specific implementation.

 open(): Opens a connection to the input source and prepares it for extracting
student records. If a connection cannot be opened, an exception is raised.

 close(): Closes the connection to the input source. If the connection is not
currently open, an exception is raised.

 fetchRecord(): Extracts the next student record from the input source and
returns a reference to a storage object containing the data. None is returned
when there are no additional records to be extracted. An exception is raised
if the connection to the input source was previously closed.

 fetchAll(): The same as fetchRecord(), but extracts all student records


(or those remaining) from the input source and returns them in a Python list.

Creating the Report


The program in Listing 1.5 uses the Student File Reader ADT to produce the
sample report illustrated earlier. The program extracts the student records from
the input source, sorts the records by student identification number, and produces
the report. This program illustrates some of the advantages of applying abstraction
to problem solving by focusing on the “what” instead of the “how.”
By using the Student File Reader ADT, we are able to design a solution and
construct a program for the problem at hand without knowing exactly how the
data is stored in the external source. We import the StudentFileReader class
from the studentfile.py module, which we assume will be an implementation of
the ADT that handles the actual data extraction. Further, if we want to use this
same program with a data file having a different format, the only modifications
required will be to indicate a different module in the import statement and possibly
a change to the filename specified by the constant variable FILE NAME.
The studentreport.py program consists of two functions: printReport() and
main(). The main routine uses an instance of the ADT to connect to the external
source in order to extract the student records into a list. The list of records is then
1.5 Application: Student Records 25

Listing 1.5 The studentreport.py program.

1 # Produces a student report from data extracted from an external source.


2 from studentfile import StudentFileReader
3
4 # Name of the file to open.
5 FILE_NAME = "students.txt"
6
7 def main():
8 # Extract the student records from the given text file.
9 reader = StudentFileReader( FILE_NAME )
10 reader.open()
11 studentList = reader.fetchAll()
12 reader.close()
13
14 # Sort the list by id number. Each object is passed to the lambda
15 # expression which returns the idNum field of the object.
16 studentList.sort( key = lambda rec: rec.idNum )
17
18 # Print the student report.
19 printReport( studentList )
20
21 # Prints the student report.
22 def printReport( theList ):
23 # The class names associated with the class codes.
24 classNames = ( None, "Freshman", "Sophomore", "Junior", "Senior" )
25
26 # Print the header.
27 print( "LIST OF STUDENTS".center(50) )
28 print( "" )
29 print( "%-5s %-25s %-10s %-4s" % ('ID', 'NAME', 'CLASS', 'GPA' ) )
30 print( "%5s %25s %10s %4s" % ('-' * 5, '-' * 25, '-' * 10, '-' * 4))
31 # Print the body.
32 for record in theList :
33 print( "%5d %-25s %-10s %4.2f" % \
34 (record.idNum, \
35 record.lastName + ', ' + record.firstName,
36 classNames[record.classCode], record.gpa) )
37 # Add a footer.
38 print( "-" * 50 )
39 print( "Number of students:", len(theList) )
40
41 # Executes the main routine.
42 main()

sorted in ascending order based on the student identification number. The actual
report is produced by passing the sorted list to the printReport() function.

Storage Class
When the data for an individual student is extracted from the input file, it will
need to be saved in a storage object that can be added to a list in order to first
sort and then print the records. We could use tuples to store the records, but we
Exploring the Variety of Random
Documents with Different Content
A carcair of hard narrow stone,
To bring all unto heaven.[462]

Of Ultan of Arbreccan he says—

Ultan loves his children;


A carcair for his lean side,
And a bath in cold water
In the sharp wind he loved.[463]

Of Molaissi of Devenish he says—

Molaissi of the lake loves


To be in a carcair of hard stone.[464]

Adamnan, too, tells us of Feargna, or Virgnous, who, ‘after having


lived for many years without reproach in obedience among the
brethren, led an anchoretic life for other twelve years, as a victorious
soldier of Christ, in the abode of the anchorites in Muirbulcmar.’[465]
This was, he also tells us, in the island of Hinba, which can be
identified with Eilean na Naomh, one of the Garveloch isles, and
here, in this solitary isle where there is little to disturb them, we find
the remains of this abode of the anchorites in connection with other
remains which are evidently the foundations of an early monastic
establishment. It consists of two circular dome-shaped buildings
joined together, built of uncemented stone. The larger one is
internally fourteen feet in diameter; the other, a part of the beehive
roof of which still remains, is about a foot less. The two buildings
communicate with each other by means of a square-shaped doorway
through the points of contact, and the larger one with the outside by
another doorway of a similar kind facing south-west.[466]
The other form of this solitary life was one in which the inmate of
a monastery withdrew from it altogether, and sought out some
remote and desert spot or island in which he might pass the rest of
his life in total solitude. Such retreats were called emphatically
‘Deserts.’ Of this desire, which with many became almost a passion,
Adamnan gives us an instance in Cormac ua Leathan. Adamnan calls
him ‘a truly pious man, who no less than three times went in search
of a desert in the ocean, but did not find it;’ and he says Columba
thus prophesied of him: ‘In his desire to find a desert, Cormac is this
day, for a second time, now embarking from that district which lies
on the other side of the river Moda, and is called Eirris Domno; nor
even this time shall he find what he seeks, and that for no other
fault than that he has irregularly allowed to accompany him on the
voyage a monk who is going away from his own proper abbot
without obtaining his consent.’[467] Again he tells us that Cormac
made another attempt to discover a desert in the ocean, and
Columba, who was then at the court of King Brude, says to the king
in the presence of the ruler of the Orkneys, ‘Some of our brethren
have lately set sail, and are anxious to discover a desert in the
pathless sea. Should they happen, after many wanderings, to come
to the Orkney islands, do thou instruct their chief, whose hostages
are in thy hand, that no evil befall them within his dominions;’ and
Adamnan tells us he did arrive in the Orkneys. On his third voyage,
Cormac sailed for fourteen days and nights due north, before a
south wind, without seeing land; and, when the wind changed to the
north, he returned again to Iona,[468] without having in any of his
three voyages succeeded in discovering such a ‘desert’ as he sought
for.
Anchorites called Those who devoted themselves to such a
Deoraidh De or solitary life were said to give themselves up to
God’s pilgrims. God,[469] and the name of Deoraidh, literally
strangers, was applied to them as ‘strangers and pilgrims’ in the
religious sense of the term, and ‘Deoraidh De,’ or pilgrims of God.[470]
But their connection with the monastery from which they emerged
was not entirely severed; for, as we have seen, when the abbacy
became vacant, the Deoraidh De, or pilgrim, was entitled to succeed
in the fifth place; and the Brehon Laws provide that if a bishop
commit certain offences, ‘the Ferleginn, or lector, shall be installed in
the bishopric, and the bishop shall go into the hermitage or
pilgrimage of God’ (Aibilteoiracht no in Deoruighecht De).[471]
The third order of Towards the end of the sixth century this
Irish saints passion for a solitary life had increased so much
Eremitical. that it tended greatly to break up the monastic
system, and became embodied in what was termed the third order
of saints; and, while the second order expresses a purely monastic
church, this third order which succeeded it, was Eremitical. ‘It was,’
says the Catalogue, ‘of this sort. They were holy presbyters and a
few bishops; one hundred in number; who dwelt in desert places,
and lived on herbs and water and the alms of the faithful. They
shunned private property; they despised all earthly things, and
wholly avoided all whispering and backbiting; and they had different
rules and masses, and different tonsures—for some had the coronal
and others the hair; and a different paschal festival—for some
celebrated the Resurrection on the fourteenth moon, or sixteenth,
with hard intentions. These lived during four reigns, and continued
to that great mortality,’ that is, from about 600 to 666. In 634, as we
have seen, the church of the southern half of Ireland had conformed
to Rome, while the northern Irish were not brought over to the
Roman system till the end of the century. What, therefore, is alluded
to, when they are said to have different masses and different
tonsures, is that this order consisted of two parties—one belonging
to the southern Irish which had adopted the coronal tonsure and the
Roman method of calculating Easter; while the other in these
respects adhered to the customs of their fathers. They appear at this
time not only to have lived a hermit life in the desert, but to have
founded eremitical establishments, where a number of hermits lived
in separate cells within the same enclosures. To both the name of
Desert or Diseart was usually given; and Colgan mentions no fewer
than ten establishments, and the Annals of the Four Masters
fourteen, the names of which commence with the word Diseart.
Among those who belonged to the party who adhered to the
customs of their fathers was that ‘Beccan Solitarius,’ or the Solitary,
to whom, along with Segine of Iona, Cumine in 634 addressed his
letter regarding the proper time for keeping Easter; and it shows the
importance now attached to this mode of life, that he is placed on
the same platform with the abbot of Iona. Tighernac records, in the
year 677, the death of ‘Beccan Ruimean in an island of Britain;’ and
he appears in the Martyrologies as ‘Becan Ruim.’[472] His hermitage
was therefore in one of the Western Isles; and what island that was
we learn from his epithet of Ruimean or Ruim, that is, of the island
of Rum. The names of seven bishops and eight presbyters who
belonged to this order are given in the Catalogue, but they were
mainly connected with the party which had conformed to Rome. The
first of the presbyters named is Fechin of Fore; he is the Vigeanus of
the Scottish Calendar, to whom the church of Arbroath was
dedicated, and probably that of Ecclefechan, or Fechan’s church, in
Dumfriesshire. In an island on the west coast of Ireland called
Ardoilean, or High Island, an uninhabited and almost inaccessible
island off the coast of Connemara, is one of the most interesting and
best preserved specimens of these Anchoretical or Eremitical
establishments, which is attributed to this Fechin. It consists of a
Cashel, or uncemented stone wall, nearly circular, enclosing an area
of one hundred and eight feet in diameter. Within this enclosure
there is an oratory, one of the widest of these ancient structures,
measuring internally twelve feet by ten, and ten feet in height. The
doorway is two feet wide and four feet six inches high, having
inscribed on its horizontal a cross similar to one on the lintel of the
doorway of St. Fechin’s church at Fore. On the east side of the
oratory is an ancient stone sepulchre like a Pagan kistvaen. There
are also within the enclosure two clochans, or dome-roofed cells—
one externally round, but internally a square of nine feet, and seven
feet six inches high. The other is circular, and internally seven feet
by six, and eight feet high. The doorways are two feet four in width,
and only three feet six in height. On the other side are a number of
smaller cells, about six feet long by three wide and four feet high,
and are mostly covered with rubbish.[473] There are no buildings
adapted for a cœnobitical life; and it is probably a good specimen of
the eremitical establishments of this third order of the saints.
Deicolæ termed The ancient document termed the Catalogue of
in Ireland Ceile the Saints, which affords us such a valuable clue
De. to the main characteristics of the Irish Church
during these different periods, leaves us at the period of the great
pestilence in the year 666; but we find that after that date the
nomenclature of the Continental anchorites begins to appear, in an
Irish form, attached to the eremitical class in the Irish Church. In
lieu of the term Deicolæ, which as we have seen, was from the
earliest period the designation of those who adopted what they
considered the higher form of religious life, peculiarly the ‘cultus’ of
God and the Father, we find these Irish anchorites having the term
of Ceile De applied to them. These terms, though not etymologically
equivalent, may be considered as correlative,[474] and intended to
represent the same class; and as Christicola becomes in Irish
Celechrist, so Deicola assumes in Irish the form of Ceile De.[475]
There is a poem in the Leabhar Breac attributed to St. Mochuda of
Rathen, who died in 636, which gives us a picture of the constituent
elements of the Irish Church at this period. It bears this title: ‘Here
begins the rule of Mochuta of Rathen, inculcating ten
commandments upon every person;’ and consists of nine sections.
Of these, the title of the second is, ‘Of the occupations of a bishop
here;’ of the third, ‘Of the abbot of a church;’ of the fourth, ‘Of the
occupations of a priest;’ of the fifth, ‘Shouldst thou be a person’s
anmchara, or soul’s friend?’ of the sixth, ‘Of the occupations of a
monk;’ and of the seventh, ‘Of the Cele De, or of the clerical
recluse,’[476] thus distinguishing the Cele De from the monk.
Deicolæ and Ceile These Ceile De, however, show precisely the
De show the same characteristics which belonged to the
same Deicolæ of the Continent. Like the Deicolæ, they
characteristics.
were Anchorites, for we find that, when the name
of Cele De appears as a personal title, it is borne by one who had
lived as a solitary in a desert, or who is termed an Anchorite. Thus
Angus the Hagiologist, who founded a desert called after his name
Disert Aengus, now Disert Enos, is well known as Aengus Cele De;
Comgan, whose death is recorded in the Ulster Annals in 869 as
‘Comgan Fota, Anchorite of Tamhlacht,’ appears in the Calendar of
Tamhlacht as ‘Comgan Cele De;’ and in the earliest notice of the Cele
De at Clonmacnois, in 1031, we find that Conn nambocht, or ‘of the
poor,’ is termed Head of the Cele De and anchorite of Clonmacnois.
[477]
Again, like the Deicolæ, they are the ‘people of God.’ Thus the
Ulster Annals tell us that in 921 ‘Armagh was pillaged on the
Saturday before St. Martin’s Day, which was the 10th of November,
by Gofrith, grandson of Ivar, and his army, who saved the houses of
prayer with their people of God, that is, Cele De, and their sick, and
the whole church town, except some houses which were burned
through neglect.’[478] Like the Deicolæ, they too claimed to be
strangers and pilgrims in the religious sense of the term; hence Cele
De is occasionally used in the sense of stranger. Dr. Reeves gives us
a curious instance of this. In one of the Irish MSS. in the Bodleian
Library is an Irish translation of a Latin tract ‘de Bragmannis,’
containing a supposed correspondence between Alexander the Great
and Dindimus, king of the Brahmins. In this tract occurs the
sentence, ‘We are not, says Dindimus, inhabitants of this world, but
strangers. Nor did we come into this world that we might remain,
but that we might pass through. We hasten to the lares of our
fathers,’ etc., which is thus translated: ‘Not of the inhabitants of the
present world are we, I tell thee, O Alexander, said Dinnim; but Cele
De is our title. We do not accept land unnecessarily in the world; for
our patrimony is before us, namely heaven, with its abodes and
rewards.’[479] Thus fully expressing the sentiment of the Brahmins
being strangers and pilgrims in the same sense as were the Cele De.
In a lake in the county of Tipperary, formerly called Lochcre, but
afterwards Monaincha, there were two islands: on one a monastery
was founded in the sixth century; and on the other, termed
Innisnambeo, or the island of the living, a church was founded in the
eighth century by St. Elair, whose death is recorded on 7th
September 807 as ‘anchorite and scribe of Loch Crea.’[480] This island
was visited by Giraldus Cambrensis in the twelfth century, and his
description will show us the two churches—the ancient monastic
church and the anchorite church of the Cele De—side by side. He
says, ‘In South Munster is a lake containing two isles; in the greater
is a church of the ancient religion; and in the lesser a chapel wherein
a few celibates, called Cœlicolæ or Colidei, devoutly serve. Into the
greater no woman or any animal of the feminine gender ever enters
but it immediately dies. This has been proved by many experiments.
In the lesser isle no one can die; hence it is called “insula viventium,”
or the island of the living.’[481]
Ceile De brought Like the Deicolæ, they evidently came under
under the the canonical rule. The Irish Annals record the
canonical rule. following singular entry:—‘In this year (811) the
Cele De came over the sea with dry feet without a vessel; and a
written roll was given him from heaven, out of which he preached to
the Irish; and it was carried up again when the sermon was finished.
This ecclesiastic (literally son of the church) used to go every day
southwards across the sea, after finishing his sermon.’[482]
Eliminating the miraculous element, we have here an ecclesiastic,
whose title is given in the Irish form of Cele De, coming from the
Continent with a written precept, which he urged upon the Irish.
This was sixty-eight years after Saint Chrodegang framed his rule for
the canonical life, and also after the revised rule was framed
containing the urgent appeal of the Deicola to all the Deicolæ over
the world, and only five years before the Council of Aix-la-Chapelle.
We may therefore reasonably conclude that what the ecclesiastic
called the Cele De introduced into Ireland was the canonical rule.
There is also preserved in the Leabhar Breac a prose rule attributed
to Maelruain of Tamhlacht, who died in 792, and the title is ‘Here
beginneth the rule of the Cele De, from what Maelruain
composed.’[483] This rule, however, was evidently not intended for a
monastic body, and shows more resemblance to the canonical rule.
[484]
The Cele De are only mentioned in a few places in Ireland. Nine
only are enumerated by Dr. Reeves. These are Tamhlacht, if
Maelruain’s establishment belongs to this order, Armagh,
Clonmacnois, Clondalkin, Monaincha, Devenish, Clones, Pubble and
Scattery. These could hardly then be the representatives of the great
monastic church, but must have been a new order which had not
spread very widely among the churches; and Dr. Reeves admits that
‘possibly the institution of Maelruain may have borrowed from or
possessed some features in common with the order of canons; for
certain it is that in after ages both the Keledei of Scotland and the
Colidei of Ireland exhibited in their discipline the main characteristics
of secular canons.’[485] Thus we find he again says, ‘the Cele De of
Armagh occupying very much the same position as the Colidei of
York, as canons of the cathedral, and latterly having the name
Latinised into the same form.’
Cele De, called Legend of Saint In Scotland the name takes
Keledei in Servanus. the form of Keledei; and they
Scotland, and make their first appearance in the territory of the
first appear in
territory of southern Picts after the expulsion of the
southern Picts. Columban monks. This we learn from the history
of Servanus or St. Serf. His life is found in
apparent connection with that of Kentigern, but the tale that it tells
is very different from that which we find in the lives of the latter
saint. Its story is as follows: There was a king in the land of Canaan
called Obeth, son of Eliud, and his wife was Alpia, daughter of a king
of Arabia. As usual in such legends, the worthy couple had no
children for twenty years, and then, after they had often prayed to
God and offered alms, and the whole people had fasted three days
and nights, comes the usual vision, and they have two sons. The
name of the one was Generatius, that of the other Malachias, or
Servanus. He was called Servanus because he served God day and
night; and this name was given him by Magonius, bishop of
Alexandria, who baptized him. His father dies when he was seven
years old. He then studies in Alexandria for thirteen years, when he
receives from the bishop the monastic habit. After thirty years he
receives priest’s orders from the same bishop, and then returns to
Canaan, where all the Canaanites elect him bishop. Here he remains
twenty years erecting monasteries and churches. An angel then
appears and gives him the usual mandate to leave his country and
kindred. He takes leave of all the clerics and laics of his bishopric,
and he goes with sixty soldiers (that is, of Christ) to the banks of the
Nile, crosses it and goes to the Red Sea, which he crosses, as usual,
dryshod, and thence to Jerusalem, where he remains seven years as
its patriarch, in room of bishop Jacob, patriarch of Jerusalem. Here
an angel takes him up Mount Sion, and shows him the wood of the
true cross, from which he cuts three pastoral staves. Then he goes
to Constantinople, where he remains three years. Thence to Rome,
where he finds the papal throne vacant, and he is elected pope and
fills the vacant chair of St. Peter seven years. The angel again tells
him he must go forth to distant lands. He goes forth followed by a
great number of clerics and people, men and women, and he tells
them to divide themselves into two parts, one of which must remain
in Rome, and the other accompany him on his mission. He crosses
the Alps, and after several adventures, arrives at the Ictian Sea or
Straits of Dover, with seven thousand soldiers (of Christ), and
crosses it dryshod. They then go from place to place till they arrive
at the river Forth. Adamnan, at this time an abbot in Scotland, meets
him on Inchkeith, and receives him with much honour. Servanus
asks him how he is to dispose of his family and companions.
Adamnan tells him they may occupy Fife, and from the Mount of the
Britons to the Mount which is called Okhel, that is, the Ochil Hills.
Servanus then goes with a hundred followers to Kinel, and throws
across the sea his rod, which becomes an apple-tree, called Morglas
by the moderns. He then goes to the place called Culenros,
purposing to live there, and removes the thorns and brushwood
which abounded there. The king who then ruled over the Picts,
Brude, son of Dargart, is wroth because he resided there without his
leave, and sends to have him killed. There is then the usual deadly
sickness of the king, and the cure through the prayers of the saint;
and the king gives him the place where he inhabits as an offering for
ever. Servanus then founds and dedicates the church and cemetery
at Culenros, or Culross. Then he goes to Lochleven to see Adamnan,
who receives him there, and shows him an island in that lake well
adapted for his religious community which is granted him. Servanus
founds a monastery in that island in which he remains seven years,
and from thence he goes about the whole region of Fife, founding
churches everywhere. The other places mentioned in this life in
connection with him are the cave at Dysart on the north shore of the
Firth of Forth, where he had his celebrated discussion with the devil,
and where the memory of St. Serf is still held in honour;
Tuligbotuan, or Tullybothy, Tuligcultrin, or Tillicoultry, Alveth and
Atheren, now Aithrey, all in the district on the north side of the
Forth, extending from Stirling to Alloa. The only other place
mentioned is his ‘Cella Dunenense,’ or cell at Dunning in Stratherne,
where he slew a dragon with his pastoral staff, in a valley still called
the Dragon’s Den. Finally, ‘after many miracles, after divine virtues,
after founding many churches, the saint, having given his peace to
the brethren, yielded up his spirit in his cell at Dunning, on the first
day of the kalends of July;’ and his disciples and the people of the
province take his body to Culenros, and there, with psalms and
hymns and canticles, he was honourably buried; and so ends the
life.[486] Here we have the same strange eastern origin, the same
journey to the west, the same occupation of the papal throne, as we
found in the legend of Boniface. This feature seems to characterise
the legends of those missionaries who promoted the great change
by which a new order of clergy, under the influence of the Roman
Church, superseded the Columban monks in the eastern and
northern districts of Scotland; and probably the invention had no
greater motive than to separate them, in a very marked manner,
from the clergy of the older church, and to give weight and authority
to their promotion of the influence of the Roman party.
Servanus In this case, however, an older Irish document
introduces gives him a closer connection with the west. In
Keledei, who are the tract on the mothers of the saints, which is
hermits.
ascribed to Aengus the Culdee, in the ninth
century, we are told that ‘Alma, the daughter of the king of the
Cruithnech,’ or Picts, ‘was the mother of Serb, or Serf, son of Proc,
king of Canaan, of Egypt; and he is the venerable old man who
possesses Cuilenros, in Stratherne, in the Comgells between the
Ochill Hills and the sea of Giudan.’[487] Here Alpia, a name which has
a very Pictish look, the daughter of the king of Arabia, becomes
Alma, the daughter of the king of the Picts, and the husband of a
Pictish princess must have belonged to a race nearer home than the
people of Canaan, here placed on the west bank of the Nile and
connected with Egypt. The Scotch part of the legend, like that of
Bonifacius, is supported by the dedications, all the churches in the
places mentioned in connection with him being dedicated to St. Serf.
The chronology of this part of the Life, too, is quite consistent; we
find no anachronisms in it, and there is not a syllable about his being
a disciple of Palladius or the teacher of Kentigern. The Brude, son of
Dargart, of the Life, may be identified with Brude, son of Derile, who
reigned from 697 to 706, and preceded that Nectan, son of Derile,
who expelled the Columban monks from his kingdom. Brude appears
in one of the chronicles, which seems to have been connected with
Lochleven, as Brude, son of Dargart; and the chronicle adds, ‘in
which time came Saint Servanus to Fife.’[488] Then Adamnan, who is
brought into such close connection with Servanus, died in 704, only
two years before the death of Brude; and there were, as we know,
the most friendly relations between them. Now there is in the
Chartulary of St. Andrews a memorandum of some early charters in
the Celtic period, and one of them is a grant by which ‘Brude, son of
Dergard, who is said by old tradition to have been the last of the
kings of the Picts’—which however he was not—‘gives the isle of
Lochlevine to the omnipotent God, and to Saint Servanus, and to the
Keledei hermits dwelling there, who are serving, and shall serve,
God in that island.’ In another, ‘Macbeth, son of Finlach, and Gruoch,
daughter of Bodhe, king and queen of the Scots, give to God
omnipotent, and the Keledei of the said island of Lochlevine,
Kyrkenes.’ And in a third, ‘Macbeth gives to God and Saint Servanus
of Lochlevyne, and the hermits there serving God, Bolgyne.’[489] We
thus see that the establishment founded by Servanus about the
beginning of the eighth century was one of hermits, and that they
bear the name of Keledei. There is nothing inconsistent with
probability that they may have been introduced by Adamnan, after
he had himself conformed to Rome and was endeavouring to bring
over his brethren, and that that part of the Life which brings him to
the south shore of the Firth of Forth—in other words, from
Northumbria—when he is met in Inchkeith by Adamnan, may be
perfectly true.
Keledei of Jocelyn of Furness, in his Life of Kentigern,
Glasgow, who tells us that he ‘joined to himself a great many
were solitary disciples whom he trained in the sacred literature
clerics.
of the Divine law, and educated to sanctity of life
by his word and example. They all with a godly jealousy imitated his
life and doctrines, accustomed to fastings and sacred vigils at certain
seasons, intent on psalms and prayers and meditation on the Divine
Word, content with sparing diet and dress, occupied every day and
hour in manual labour. For, after the fashion of the primitive church
under the Apostles and their successors, possessing nothing of their
own, and living soberly, righteously, godly and continently, they
dwelt, as did Kentigern himself, in single cottages, from the time
when they had become mature in age and doctrine. Therefore these
solitary clerics were called in common speech Calledei.’[490] In
assigning the Calledei, or Keledei of Glasgow to the time of
Kentigern, Jocelyn is no doubt guilty of as great an anachronism as
when he assigned to him Servanus as a teacher; and the statement
belongs to the same period in Kentigern’s supposed history, when he
first became bishop of Glasgow; but this part of his life is very
problematical, ‘and the historical part of his legend probably begins
only when he returned from Wales after the battle of Ardderyd.
Here, however, he appears connected with the Monastic Church of
Wales, he is followed by six hundred and sixty-six of his monks of
Llanelwy, and Jocelyn tells us that these monks all rest, as the
inhabitants and countrymen assert, in the cemetery of the church of
the city of Glasgow.’ Jocelyn, however, wrote while there existed
bodies of Keledei in Scotland, and he is no doubt reporting a
genuine tradition as to the original characteristics of the Culdean
clergy before they became canons. What he here describes is simply
a community of anchorites, or hermits. Servanus was contemporary
with that Scottish Sedulius, bishop of the Britons, who had
conformed to Rome, and whom we find bishop of the Strathclyde
Britons after they had acquired their independence and became
freed from the yoke of the Angles. It is to this period that these
Calledei of Glasgow properly belong; and this connection with the
real Servanus may have led to the history of this period having been
drawn back, and both Calledei and Servanus associated with the
great apostle of Glasgow in popular tradition.
Legends We have seen that in the year 710, Nectan
connected with king of the Picts placed his kingdom under the
the foundation of patronage of St. Peter, and we have now reached
St. Andrews.
the period when that apostle was superseded by
St. Andrew as the patron saint of the kingdom. Two separate
editions of the legend of the foundation of St. Andrews have come
down to us. The older of these is a document of the twelfth century,
and appears in connection with the earliest of the chronicles in
which the century which intervened between the last of the Scottish
kings of Dalriada and the first of the Scottish dynasty which
ascended the throne of the Picts is suppressed, and the line of the
Scottish kings of Dalriada made immediately to precede Kenneth
mac Alpin, the founder of the latter dynasty. The second form of the
legend is longer and more elaborate, and emerges, at a somewhat
later period, from St. Andrews itself. The older legend bears this
title: ‘How it happens that the memory of St. Andrew the apostle
should exist more widely in the region of the Picts, now called
Scocia, than in other regions; and how it comes that so many
abbacies were anciently established there, which now in many cases
are by hereditary right possessed by laymen.’[491] The legend itself
obviously consists of five parts, very inartistically put together. In the
first, we are told that St. Andrew, the brother-german of St. Peter,
preached to the northern Scythian nations, and sought the Pictones,
then the Achæans, and finally the town of Patras, where he was
crucified on the second day before the kalends of December, and
where his bones were kept down to the time of Constantine the
Great, and his sons Constantine and Constans, that is, for a space of
two hundred and seventy years. In their reign they were taken up
and transferred to Constantinople and there enshrined, and
remained there till the time of the Christian emperor Theodosius, a
period of about one hundred and ten years. In the second part we
are told that a king of the Picts, called Ungus, son of Urguist, rising
with a great army against the British nations inhabiting the southern
part of the island, and cruelly ravaging and slaying, came at last to
the plain of Merc, or the Merse. Here he wintered. Then came nearly
the whole of the natives of the island and surrounded him, wishing
to destroy him with his army; but, next day, when the king was
walking with his seven most intimate companions, a divine light
surrounded them, and, falling on their faces, they heard a voice from
heaven saying, ‘Ungus, Ungus, hearken unto me, the apostle of
Christ called Andrew, who am sent to defend and protect you.
Behold the sign of the cross in the air; let it advance against your
enemies. You must, however, offer up the tenth part of your
inheritance as an oblation to God omnipotent, and in honour of St.
Andrew.’ On the third day he divides his army into twelve troops,
each preceded by the sign of the cross, and they were victorious.
The king then returned home resolved to immolate the tenth part of
his inheritance to God and St. Andrew the apostle. The third part of
the legend tells us that one of the custodians of the body of St.
Andrew the apostle at Constantinople, when he had taken counsel
and fasted for two, three, nay four days, and prayed for the mercy
of God, was admonished by a vision that he must leave his country
and kindred and home and go to a land which would be shown him.
Accordingly he went, conducted by the angel, and arrived safely at
the summit of the King’s Mount, that is, Rigmund. The fourth part
tells us that, in the same hour in which he sat wearily with his seven
companions, a divine light overwhelmed the king of the Picts, who
with his army was coming to a particular place called Kartenan; and
not bearing the light, they fell on their faces, and deaf and blind
were healed to the number of seven; and one, who had been blind
from his birth and received sight, cried with a loud voice that he saw
the place full of the visitation of angels; and the king with his army
came to the place which the Lord had shown to the blind man. The
fifth part begins, ‘Regulus, therefore, a monk, a pilgrim from the city
of Constantinople, with the relics of St. Andrew, which he had
brought with him, met the king at the gate which is called Matha,
that is, Mordurus. They saluted each other, and fixed their tents
where now is the Royal Hall.’ King Ungus then gave that place and
city to God and St. Andrew the apostle, that it should be the head
and mother of all the churches which are in the kingdom of the
Picts. ‘Regulus, therefore, abbot and monk, with his dear
companions, occupied that place, leading a monastic life, and
serving God day and night, in holiness and justice all the days of his
life, and their bodies rest there. Regulus held in his hand and power
the third part of the whole of Scocia, and ordained and distributed it
in abbacies. This country commended itself, by the situation and
amenity of its localities, to Picts, Scots, Danes, Norwegians, and
others, who arrived to ravage the island; and, if they needed refuge,
it offered them always a safe receptacle, and received them within
her as in their own camp.’ The first part of this legend may be put
aside as connected with the history of the relics of St. Andrew prior
to the fifth century, and is true enough; but it is obvious that the
other parts are inconsistent with each other, and appear to be
derived from different sources and to have been inartistically
brought together. Thus, in the third part, an unnamed custodier of
the relics brings them from Constantinople and lands at Rigmund;
but in the fifth part Regulus, a monk, brings them from
Constantinople and arrives at the gate called Matha; and this last
part seems unconnected and as if it belonged to a different narrative
from those that precede.
The second legend, which emanated from St. Andrews itself, is
much more elaborate.[492] The first part of this form of the legend
states that in the year 345 Constantine collected a great army to
invade Patras, in order to avenge the martyrdom of St. Andrew and
remove his relics; that an angel appeared and ordered Regulus, the
bishop, with his clergy, to proceed to the sarcophagus in which the
bones of St. Andrew were enshrined, and to take a part of them,
consisting of three fingers of the right hand, a part of one of the
arms, the pan of one of the knees, and one of the teeth, and
conceal them; that the following day Constantine entered the city
and carried off to Rome the shrine containing the rest of the bones;
that he then laid waste the Insula Tyberis and Colossia, and took
from thence the bones of St. Luke and St. Timothy, and carried them
to Constantinople along with the relics of St. Andrew. The second
part of this legend is an elaboration of the second part of the other.
The Pictish king is called Hungus, son of Ferlon. His enemy is
Adhelstan, king of the Saxons; and he is encamped at the mouth of
the river Tyne. The night before the battle St. Andrew appears to
Hungus in a dream and promises him the victory, and tells him that
his relics will be brought to his kingdom, and the place where they
are brought will become honoured and celebrated. The people of the
Picts swear to venerate St. Andrew ever after if they prove
victorious. Adhelstan is defeated, and his head is taken off and
carried to a place called Ardchinnechun, or Queen’s Harbour.
According to the third part of this form of the legend, some days
after this victory the angel of God appears a second time to the
blessed bishop Regulus, and warns him to sail towards the north
with the relics of St. Andrew which he had reserved, and, wherever
his vessel should be wrecked, there to erect a church in honour of
St. Andrew. Bishop Regulus, accordingly, accompanied by holy men,
sails towards the north, voyages among the islands of the Grecian
Sea for a year and a half, and wherever he lands erects an oratory in
honour of St. Andrew. At length they direct their sails towards the
north, and on the eve of St. Michael arrive at the land of the Picts, at
a place once called Muckros, but now Kylrimont; and, his vessel
being wrecked, he erects a cross he had brought from Patras, and
remains there seven days and nights. Having intrusted the care of
this place to the seniors St. Damian and his brother Merinach,
Regulus and the rest go with the relics to Forteviot, and find there
the three sons of King Hungus—viz. Owen, Nectan, and Finguine—
who, being anxious as to the life of their father, then on an
expedition in the region of Argathelia, give a tenth part of Forteviot
to God and St. Andrew. They then go to a place called Moneclatu,
but now Monichi, and there Finchem, the queen of King Hungus, is
delivered of a daughter called Mouren, who was afterwards buried at
Kylrimont; and the queen gives the place to God and St. Andrew.
They then cross the mountain called the Mounth, and reach a place
called Doldencha, but now Chondrohedalvan, where they meet King
Hungus returning from his expedition. The king prostrates himself
before the relics, and this place also is given to God and St. Andrew.
They then return across the Mounth to Monichi, where a church was
built in honour of God and the apostle; thence to Forteviot, where
also a similar church is built. King Hungus then went with the holy
men to Chilrymont, and, making a circuit round a great part of that
place, immolated it to God and St. Andrew for the erection of
churches and oratories. King Hungus and Bishop Regulus and the
rest proceeded round it seven times, Bishop Regulus carrying on his
head the relics of St. Andrew, his followers chanting hymns, and
King Hungus following on foot, and after him the magnates of the
kingdom. Thus they commended that place to God, and protected it
with the king’s peace; and, in commemoration, the holy men
surrounded it with twelve stone crosses. King Hungus afterwards
gave to the basilica of the holy apostle, as a parochia, the land
between the sea called Ishundenema and the sea called Sletheuma,
and in the district adjacent to it the land within a line drawn from
Largo through Ceres to Naughton. King Hungus gave this place, viz.
Chilrymont, to God and St. Andrew his apostle, with waters,
meadows, fields, pastures, moors and woods, as a gift for ever, and
granted the place with such liberty that its inhabitants should be free
and for ever relieved from the burden of hosting, and building
castles and bridges, and all secular exactions. Bishop Regulus then
chanted the Alleluia, that God might protect that place in honour of
the apostle; and, in token of this freedom, King Hungus took a turf
in presence of the Pictish nobles, and laid it on the altar of St.
Andrew, and offered that same turf upon it. This part of the legend
concludes with the names of thirteen Pictish witnesses of royal race,
whose names have been apparently taken at random from the
earliest part of the list of the Pictish kings.
Older legend Now these two forms of the legend are in very
belongs to striking contrast to each other, especially in the
foundation of part which Regulus plays in each. In the former
monastery in
sixth century. and older legend, he makes his first appearance
when he meets the king at the gate called Matha
with the relics. In the latter he is introduced into the history of the
removal of the relics from Patras, and reserves a portion to be
conveyed to a distant land; and thus, along with him, the whole
history is removed back to the fourth century. His character too, and
that of his foundation, is quite different in the two legends. In the
older he is presented to us as a monk and abbot. He and all his
people follow a monastic life at St. Andrews, and he founds abbacies
or monasteries. He possesses the third part of all Scotia, and
devotes it to the foundation of abbacies or monasteries throughout
the whole of it. In the later legend he appears as a bishop. He has
two presbyters and two Deacons among his followers, and he founds
churches and oratories which are dedicated to St. Andrew. In the
one we have a purely monastic foundation; in the other a church
with secular clergy. The older legend, therefore, takes us back for
Regulus to the Monastic Church which had been founded among the
southern Picts by Columba towards the end of the sixth century, and
to it we must look for the Regulus of this form of the legend. Now,
we find it stated in the Acts of Farannan that, after the great synod
of Drumceitt in the year 573, which was attended both by Columba
and by Aidan, king of Dalriada, the former, before he returned to
Britain, founded a church in the Region of Cairbre. This was the
church of Drumcliffe, situated a little to the north of Sligo, in the
barony of Cairbury and diocese of Elphin, the foundation of which is
attributed to Columba in the old Irish Life. We are then told that on
this occasion he was met by the leading ecclesiastics of the
neighbourhood, with the men and women most noted for sanctity,
who accompanied him in some of his wanderings. Now, among
these ecclesiastics we find recorded the name of Regulus, or Riagail,
of Muicinis, an island in the lake formed by the river Shannon called
Loch Derg;[493] and this Regulus appears in the old Irish
Martyrologies on the 16th day of October. In the Felire of Angus the
Culdee there is commemorated, on that day, ‘Riagail, gifted was his
career;’ and the gloss is, ‘that is, Riagail of Muicinish, in Loch
Derg.’[494] Regulus of St. Andrews, however, is commemorated in the
Scottish Calendar on the 17th of the same month; and we find that
there is usually a confusion in the celebrations on these two days,
when the 16th day of the month is also the 17th day before the
kalends of the next month.[495] We also find that, while the name of
the Irish Regulus’ foundation is Muicinis, or the isle of swine, the
name of St. Andrews, before it received that of Chilrymont, is said in
the second legend to have been Muicross, or the promontory of
swine. It seems, therefore, to be a reasonable conclusion that the
Regulus of Muicinis, commemorated on the 16th October, and the
Regulus of Muicross, on the 17th of that month, were the same
person, and that the historic Regulus belongs to a Columban church
founded among those which Columba established among the
southern Picts during the last years of his life, and at the same time
when Cainnech of Achaboe had his hermitage there; and to those
older foundations must be appropriated the churches dedicated to
Regulus, or St. Rule.
The Columban The title of the older legend states that the
monasteries abbacies or monasteries then founded ‘in the
among the Picts territory of the Picts, which is now called Scotia,’
fell into the
hands of laymen. that is, in the districts between the Firth of Forth
and the river Spey, had to a great extent passed
into the possession of laymen; and the legend seems to attribute
this to the depredations of the occupiers of the land—the Picts,
Scots, Danes, Norwegians and others who took possession of them
as a safe refuge. The order in which these occupiers are enumerated
is historically correct; and, though the expressions are somewhat
obscure, they seem to indicate that the expulsion of the Columban
monks, which terminated the Monastic Church in these districts, had
been followed by the same process as we learn from Bede took
place in Northumbria after the Scottish monks had withdrawn from
thence. The assimilation of the church there to that of Rome, and
the reaction towards a secular clergy, appear to have led there to a
secularisation of the monasteries to a great extent. Bede gives us an
account of this in a letter written in the last year of his life, that is, in
735, to Bishop Ecgberct; and the picture he draws shows a complete
disorganisation of the monastic institution in the land, and its
usurpation by the secular world. ‘As you yourself very well know,’ he
says, ‘those who are utterly regardless of a monastic life have got
into their power so many places under the name of monasteries,
that there is no place at all which the sons of the nobility or of
veteran soldiers may occupy.’ Again, ‘But there are others guilty of a
still more grievous offence. For, though they are themselves laics,
and neither habituated to nor actuated by the love of a regular life,
yet, by pecuniary payments to the kings, and under pretext of
founding monasteries, they purchase for themselves territories in
which they may have freer scope for their lust; and, moreover, they
cause these to be assigned to them by royal edicts for an hereditary
possession;’ ‘and, though they themselves are laymen, yet they have
monks under their rule,—or, rather, they are not monks when they
assemble there, but such as, having been expelled from the true
monasteries for the crime of disobedience, are found wandering up
and down; or those whom they themselves have succeeded in
alluring from these monasteries; or, at any rate, those among their
own servants whom they have been able to induce to take the
tonsure and make a promise of monastic obedience to them. With
these motley bands they fill the cells which they have constructed.’
‘Thus,’ says Bede further, ‘for about thirty years, that is, from the
time when King Aldfrid was removed from the world, our province
has been so demented by this mad error, that from that period
scarcely has there been a single prefect who has not, during the
course of his prefectship, founded for himself a monastery of this
description. And, since this most wretched custom has become
prevalent, the ministers also and servants of the king were content
to do the same. And thus, contrary to the established order,
numberless persons are found who style themselves indiscriminately
abbots and prefects, or ministers or servants of the king; and,
though laymen might have been instructed in something of the
monastic life, not indeed by experience but by hearsay, yet these
persons have nothing in common with the character or profession
whose duty it is to give the instruction. And indeed such persons, at
their own caprice, suddenly receive the tonsure, as you are aware;
and by their own decision are made from laymen, not monks, but
abbots.’[496] This piteous wail of the true-hearted Bede seems to find
an echo in the title of the older legend of St. Andrew. King Aldfrid
died in 705, and the thirty years Bede refers to extend to the year in
which he wrote this account, and which was indeed the last of his
life. It was but twelve years after King Aldfrid’s death that King
Nectan expelled the Columban monks from his dominions. The
monasteries would naturally fall into the possession of the tribe of
the land; and, if we substitute monasteries founded by the
Columban church, from which their monks were expelled, for
monasteries and cells directly founded by laymen, it is probable
enough that the withdrawal of the Columban monks in the one
country and their expulsion in the other, with the introduction of a
secular clergy in both, was followed by similar results; and that the
kingdom of the Picts may have exhibited the greater part of these
monasteries in the hands of laymen, the semblance and the
nomenclature of the monastic institution being thus kept up without
the reality. Bede indicates that the motive for doing so was to
preserve the privileges of such foundations, such as exemption from
service and right of sanctuary, without the corresponding
obligations; and such grounds of action would be equally powerful in
the one country as in the other. Tighernac records in 747 the death
of Tuathal, abbot of Cinnrighmonadh,[497] or Kylrimont. He may have
been one of those titular abbots; but as this is the only instance in
which an abbot of Kilrymont is noticed in the Irish Annals, it is more
probable that he was the expelled abbot of the old monastery, who
had died in Ireland.
Second legend But if the historic Regulus belongs to the older
belongs to the Columban foundation at Muicross, and if the
later foundation expulsion of the Columban monks was followed
to which relics of
St. Andrew were by such results, it is equally certain that King
brought. Hungus and the reception of the relics of St.
Andrew, which is inseparably connected with him
in the legend, must be brought down to a later period, to which also
the fictitious Regulus belongs. The lists of the Pictish kings show no
Angus or Hungus, son of Fergus, till we come to the powerful king of
that name who reigned from 731 to 761; and the events ascribed to
him in the legend correspond with those of his reign. He was
engaged in war in the Merse, and he had penetrated into those parts
of Argathelia which formed the Scottish kingdom of Dalriada, on an
expedition which had for its object the entire conquest of that
kingdom, and might well lead his sons to fear for his safety. The
narrative which Bede gives us of the circumstances which led King
Nectan to place his kingdom under the patronage of St. Peter in 710
entirely excludes the possibility of the national veneration of St.
Andrew having been introduced before that date; and, while it is
obvious, from an analysis of the legends, that a fictitious and
artificial antiquity has been given to it, yet the knowledge of its true
date seems not to have been entirely extinguished by the fabulous
one: for we find a record of it in one chronicle, though not a very
early one, when it is said, ‘The zeire of God sevynn hundir lxi ye
relikis of Sanct Androw ye Apostle com in Scotland;’[498] and this year
synchronises with the last year of the reign of Angus mac Fergus,
who was one of the most powerful kings of the Picts. If, then, the
relics of St. Andrew were brought into Scotland in the reign of this
Angus, king of the Picts, the question at once arises, Where did they
come from?—and here the mind naturally reverts to the church of
Hexham. It too was dedicated to St. Andrew. It too possessed relics
of St. Andrew. But in both it preceded in date the foundation of St.
Andrews in Scotland; for Hexham was founded in 674 by Wilfrid,
who dedicated it to the apostle, and the relics were brought there by
his successor, Bishop Acca, whose episcopate lasted from 709 to
732. In one remarkable respect, too, one church was a reflection of
the other; for Wilfrid dedicated his church to St. Andrew in
consequence of his belief that he had received the gift of persuasive
eloquence through the intercession of the apostle, in answer to his
prayers offered up in the church of St. Andrew in Rome; and he
afterwards erected two chapels at Hexham, dedicated to St. Mary
and St. Michael, owing to his belief that he had recovered from a
mortal sickness through the intercession of the Blessed Virgin Mary,
announced to him in a vision by Michael the Archangel. This peculiar
combination, therefore, at Hexham, of a principal dedication to St.
Andrew with chapels to St. Mary and St. Michael, arose out of
incidents in Wilfrid’s life. And yet we find the same combination at
St. Andrews in Scotland, for the second legend tells us, after
narrating the foundation of St. Andrews, ‘Afterwards in Chilrymont
the holy men erected seven churches—one in honour of St. Regulus,
the second in honour of St. Aneglas the Deacon, the third in honour
of St. Michael the Archangel, the fourth in honour of St. Mary the
Virgin, the fifth in honour of St. Damian, the sixth in honour of St.
Brigida the virgin, and the seventh in honour of a certain virgin
Muren.’ The first of these churches belongs, of course, to the older
foundation; but here we find that the third and fourth are chapels
dedicated to St. Michael and St. Mary. There seems, too, to have
been a tradition that about this time the foundation of an episcopal
see among the Picts proceeded from Hexham. When Bede wrote his
history in 731, Acca was still living at Hexham, and exercising his
episcopal functions there apparently without disturbance; but
Simeon of Durham tells us that in 732—that is, in the following year
—Acca was expelled from his see;[499] and Prior Richard of Hexham
adds to this statement, ‘By what urgent necessity he was driven
forth, or whither he directed his steps, I do not find recorded. But
there are some who say that at that time he commenced and
prepared the episcopal see at Candida.’[500] or Whithern. He certainly
founded no see at Whithern, for we have the contemporary authority
of Bede for the fact that it had been founded some years before,
and that Pecthelm was its first bishop; but, at the time Prior Richard
wrote, the memory of the great Pictish kingdom had passed away,
the Picts of Galloway alone retained the name, and writers of that
period transferred to Galloway events that truly belonged to the
northern portion of the race. Thus Florence of Worcester placed
Trumuini as bishop of Candida, though it is clearly stated by Bede
that the Picts he presided over were those north of the Firth of
Forth; and Prior Richard, in quoting the passage from Bede, where
he says that Wilfrid’s bishopric extended over the Picts as far as
Osuiu’s dominion extended, over whom Trumuini was afterwards
placed, adds the expression, ‘because Whithern had not yet its own
bishop,’[501] thus transferring what was intended by Bede to apply to
the Picts north of the Forth to those of Galloway. The Hexham
tradition was probably no more than that it was believed Acca had
gone to the nation of the Picts and founded a bishopric among
them. It is certainly a remarkable coincidence that Acca, the
venerator of St. Andrew, and the importer of his relics into Hexham,
should have fled in 732, and that a report should have sprung up
that he had founded a bishop’s see among the Picts; and that St.
Andrews should have been actually founded by a Pictish king
between the years 736 and 761, and part of the relics of St. Andrew
brought to it at that time. Indeed, the correspondence between the
church history of the Northumbrian and Pictish kingdoms in this
respect is at this time very striking:—the Northumbrians expelling
the Columban clergy, introducing secular clergy with dedications to
St. Peter, and then dedicating Hexham to St. Andrew, and receiving
the relics of the apostle brought there by one of its bishops; and,
sixty years later, the Picts expelling the Columban monks,
introducing the secular clergy, placing the kingdom under the
patronage of St. Peter, and then receiving from some unknown
quarter the relics of St. Andrew, and founding a church in honour of
that apostle, who becomes the national patron saint. The second
legend concludes with this statement:—‘These are the names of
those holy men who brought the sacred relics of St. Andrew the
apostle into Scotia—St. Regulus himself; Gelasius the deacon;
Maltheus the hermit; St. Damian, presbyter, and his brother
Merinach; Nervius and Crisenius from the island Nola; Mirenus, and
Thuluculus the deacon; Nathabeus and Silvius his brother; Seven
hermits from the island of the Tiber—Felix, Juranus, Mauritius,
Madianus, Philippus, Eugenius, Lunus; and three virgins from
Collossia, viz., Triduana, Potentia, Cineria. These virgins are buried at
the church of St. Aneglas. Thana, son of Dudabrach, wrote this
document for King Pherath son of Bergeth, in the town of Migdele.’
The king here meant is probably the last king but one of the Picts,
called in the Pictish Chronicle Wrad son of Bargoit, who reigned from
840 to 843; and Migdele is Meigle in Perthshire.
Keledei of St. The church of St. Andrews, then, is
Andrews represented in this legend as consisting of three
originally groups—First, one of secular clergy, viz., Bishop
hermits.
Regulus himself, with two priests and two
deacons, and three others, whose quality is not given; secondly, a
group of hermits, viz., Maltheus, with two from the island of Nola,
and seven from the island of Tiber—in all, a community of ten; and,
thirdly, three virgins. The second group is that of the hermits,
representing a community of Keledei similar to those established by
Servanus in Lochleven. The legend of Triduana, which is preserved in
the Aberdeen Breviary, tells us that she led a heremitical life, with
her virgins Potentia and Emeria, in a desert place at Roscoby
(Rescobie in Forfarshire). The tyrant Nectanevus, prince of the
neighbourhood, pursued her, whereupon she fled to Dunfallad
(Dunfallandy) in Athol. There his ministers coming to her and telling
her that the beauty of her eyes had attracted the prince, she plucked
them out and gave them to them. Triduana then devoting herself to
prayer and fasting in Lestalryk, now Restalrig, in Laudonia, passed
into heaven.[502] Here, as usual, the legend is supported by the
dedications. At Rescobie is St. Triduan’s fair. Restalrig is also
dedicated to her; and here too a connection with Northumbria, to
which it then belonged, seems to peep out.
Canonical rule The canonical rule appears to have been
brought into adopted in Scotland not long after it had been
Scotland, and introduced into Ireland; for, as we learn from the
Keledei become
canons. Chronicles, two hundred and twenty-five years
and eleven months after the church of Abernethy
had been founded by Gartnach, son of Domelch, who reigned from
584 to 599, the church of Dunkeld was founded by Constantin, son
of Fergus king of the Picts, who reigned from 790 to 820. This places
the foundation of Dunkeld some time between the years 810 and
820, and the tradition of Dunkeld, as reported by Alexander Mylne, a
canon of that church in 1575, is that he placed there ‘religious men
who are popularly called Keledei, otherwise Colidei, that is God-
worshippers, who, according to the rite of the Oriental Church, had
wives, from whom, however, they withdrew while ministering, as
was afterwards the custom in the church of St. Regulus, now St.
Andrew;’[503] while Wyntoun, the prior of Lochleven, tells us that

Awcht hundyr wyntyr and fyftene


Fra God tuk fleysch off Mary schene,
Leo and Charlys bath ware dede,
And Lowys than in Charlys stede.
The kyng off Peychtis Constantyne
Be Tay than foundyd Dwnkeldyne,
A place solempne cathedrale,
Dowyd welle in temporalle.
The byschape and chanownys thare
Serẅys God and Saynct Colme, seculare,
Off oure byschoprykis, off renowne
The thryd, and reputatyowne.[504]

The date assigned by Wyntoun to the foundation of Dunkeld is


probably correct, and those religious men who Mylne says were
popularly called Keledei, Wyntoun here calls ‘chanownys seculare.’
Conclusion as to The result, then, that we have arrived at is that
origin of the the Culdees originally sprang from that ascetic
Culdees. order who adopted a solitary service of God in an
isolated cell as the highest form of religious life, and who were
termed Deicolæ; that they then became associated in communities
of anchorites, or hermits; that they were clerics, and might be called
monks, but only in the sense in which anchorites were monks; that
they made their appearance in the eastern districts of Scotland at
the same time as the secular clergy were introduced, and succeeded
the Columban monks who had been driven across the great
mountain range of Drumalban, the western frontier of the Pictish
kingdom; and that they were finally brought under the canonical rule
along with the secular clergy, retaining, however, to some extent the
nomenclature of the monastery, until at length the name of
Keledeus, or Culdee, became almost synonymous with that of
secular canon.
431. The latest and ablest supporter of the view that the
Columban monks were the Culdees is Ebrard, in his Culdeische
Kirche. He rightly gives, as the correct form of the name in Irish,
Ceile De, and properly explains Ceile as meaning ‘Socius,’ but
entirely fails in his attempt to connect the name with the Columban
Church. He finds the word Ceile in the Irish name of St. Columba,
Coluim cille, which he says should be Coluim ceile, or the Culdee,
and that the name of Urbs Coludi, given by Bede to Coldingham,
means the town of the Culdees. This is etymology of the same kind
as that which makes Kirkcaldy, the old form of which is Kyrc-aldyn,
to mean the church of the Culdees.

432. The legend of Bonifacius is printed in the Chronicles of the


Picts and Scots, p. 421.

433. Reeves’s British Culdees, p 45. Dr. Reeves remarks that, if


Rosmicbairend has been written for Rosmbaircind, the name would
be pronounced Rosmarkyn.

434. Wynton’s Chronicle, B. v. c. xiii., in series of Scottish


Historians, vol. ii. p. 58.

435. Bishop Forbes’s Calendar of Scottish Saints, p. 336.

436. Fergustus Episcopus Scotiæ Pictus huic constituto a nobis


promulgato subscripsi.—Haddan’s Councils, vol. ii. part i. p. 7. The
epithet Pictus at this period implies that he was of the race of the
Scottish Picts.

437. It is possible that Neachtan may have made up his quarrel


with the Iona monks and retired to Iona, as we find there, at the
end of a broad and elevated terrace near the present ruins, the
remains of a burying-ground called Cill-ma-Neachtan, which marks
the site of an oratory.

438. Epist. ad Eustochium.


439. Collationes, xviii. and xix.; Migne, Patrologia, vol. xix.

440. See Dupin’s Ecclesiastical History for an abstract of this


treatise, vol. iv. p. 18.

441. Isidore, De Ecc. Off., lib. ii. c. 16. Migne, Patrologia, vol. xli.

442. Bede, Hist. Ec., B. iv. c. 28. Vit. S. Cudbercti, c. 17.

443. Bede, Vit. S. Cudbercti, c. 1.

444. Religio munda, et immaculata apud Deum et Patrem hæc


est: visitare pupillos et viduas in tribulatione eorum, et immaculatum
se custodire ab hoc sæculo.—Cap. i., 27.

445. Qui aliquando non populus, nunc autem populus Dei; qui non
consecuti misericordiam, nunc autem misericordiam consecuti.
Charissimi, obsecro vos tanquam advenas et peregrinos abstinere
vos a carnalibus desideriis, quæ militant adversus animam.—Cap. ii.
vv. 10, 11.

446. Nam et vicini et monachi, ad quos sæpe veniebat, Antonium


videntes, Deicolam nuncupabant; indultisque naturæ vocabulis,
quidam ut filium, alii ut fratrem diligebant.—Migne, Patrologia, vol.
xxxv. col. 129.

447. Non illa ardua et perfecta, quæ a paucis et peregregiis


Deicolis patrantur.—Martinus de Vitæ honestæ Formula: D’Achery, iii.
312.

448. Quicunque ergo se habitaculum Dei effici voluerit, humilem et


quietum se facere contendat, ut non verborum aviditate et corporis
flexibilitate, sed humilitatis veritate cognoscatur esse Deicola: cordis
enim bonitas non verborum fictis indiget religionibus.—Migne,
Patrologia, vol. xxxvii. col. 234.
449. Colgan, A.SS., p. 115; Fleury, l. 37, c. 27. Colgan supposes
that Deicola may be the Latin form of the Irish name of Dichuill, and
this is usually assumed to be the case; but there is no authority for
it, and no other analogy between the names than an accidental
resemblance in appearance.

450. Peracto vero quadriennio, apparuit ei angelus Domini et dixit


illi, Vade ad plebem Dei, id est, Eremitas et solitarios nudis pedibus
et conversare cum eis, ut proberis per aliquot tempus. Et venit in
solitudinem et mansit cum Eremitis per 8 annos.—Colgan, Tr. Th., p.
48, recté 52.

451. Tempore illo fuit quidam Dregmo in territorio Hagustaldensis


ecclesiæ, Deum valde timens et elymosinarum operibus, prout
facultas sibi suppeditabat, haud segniter deditus ac per omnia a
comprovincialium moribus vita discordans. Erat enim miræ
simplicitatis et innocentiæ homo ac erga sanctos Dei devotionis et
venerationis immensæ. Quapropter eum omnes vicini sui in magno
honore habebant, illumque verum Dei cultorem appellabant.—Sim.
Dun., Hist. Regum (Surtees Ed.), p. 26.

452. Hefele, Concilien Geschichte, vol. iii. p. 88.

453. Ib., vol. iii. p. 306.

454. Hefele, Concilien Geschichte, vol. iv. p. 18.

455. Dilectissimis sacerdotibus ecclesiarum Christi præsulibus et


cunctis cleris in eisdem ubique et famulantibus et Deicolis omnibus
per totum mundum degentibus.

456. D’Achery, Spicilegium, vol. i. p. 565.

457. Hefele, Concilien Geschichte, vol. iv. p. 10.

458. Thorpe, Anglo-Saxon Chronicle, vol. ii. p. 27.


459. Haddan and Stubbs’ Councils, vol. iii. p. 450.

460. Reeves, The Culdees of the British Isles, pp. 59, 144.

461. Dei servitium passim nostra in gente a Cultoribus Clericis


defleo extinctum et tepefactum.—Statuta Ecclesiæ, vol. i. p. ccxiii.
See other notices there mentioned.

462. Mart. Don., p. 83.

463. Mart. Don., p. 235.

464. Ib., p. 245.

465. Adamnan, Vit. S. Col., B. iii. c. 42.

466. See for a description and ground-plan the Appendix No. I., p.
322, to the edition of Reeves’s Adamnan in series of Scottish
Historians.

467. Adamnan, Vit. S. Col., B. i. c. 6.

468. Ib., B. ii. c. 43.

469. A.D. 1007 Muredach mac Cricain do deirgiu Comarbus


Columcille ar Dia (resigns the corbeship of Columcille, or abbacy, for
God).—Chron. Picts and Scots, p. 366.

470. In the Irish Glosses, edited by Mr. Whitley Stokes, the Latin
word advona is glossed by Deorad. Among the Charters of Kells is
one founding, in 1084, a Diseart, which is given to God and devout
pilgrims; ‘no wanderer (Erraid) to have any possession till he
surrenders his life to God (do Dia) and is devout;’ and in 1000
Tempull Gerailt is rebuilt for pilgrims of God (Deoradaibh De).

471. Ancient Laws of Ireland, vol. i. p. 59.

You might also like