100% found this document useful (2 votes)
14 views

1098992Data Structures And Algorithms Using Python Necaise Rance D instant download

The document is about the book 'Data Structures and Algorithms Using Python' by Rance D. Necaise, which covers various data structures and algorithms in Python. It includes chapters on abstract data types, arrays, sets, and maps, along with exercises and programming projects. Additionally, it provides links to related ebooks and information about the book's publication and copyright.

Uploaded by

gasasemuraca
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 (2 votes)
14 views

1098992Data Structures And Algorithms Using Python Necaise Rance D instant download

The document is about the book 'Data Structures and Algorithms Using Python' by Rance D. Necaise, which covers various data structures and algorithms in Python. It includes chapters on abstract data types, arrays, sets, and maps, along with exercises and programming projects. Additionally, it provides links to related ebooks and information about the book's publication and copyright.

Uploaded by

gasasemuraca
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/ 91

Data Structures And Algorithms Using Python

Necaise Rance D download

https://ebookbell.com/product/data-structures-and-algorithms-
using-python-necaise-rance-d-21979842

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Data Structures And Algorithms Using Python And C David M Reed

https://ebookbell.com/product/data-structures-and-algorithms-using-
python-and-c-david-m-reed-5497352

Problem Solving With Algorithms And Data Structures Using Python


Second Edition 2nd Bradley N Miller

https://ebookbell.com/product/problem-solving-with-algorithms-and-
data-structures-using-python-second-edition-2nd-bradley-n-
miller-4744554

Handson Data Structures And Algorithms With Python Write Complex And
Powerful Code Using The Latest Features Of Python 37 2nd Edition 2nd
Edition Dr Basant Agarwal

https://ebookbell.com/product/handson-data-structures-and-algorithms-
with-python-write-complex-and-powerful-code-using-the-latest-features-
of-python-37-2nd-edition-2nd-edition-dr-basant-agarwal-10684212

Data Structures And Algorithms Using Visual Basicnet Michael Mcmillan

https://ebookbell.com/product/data-structures-and-algorithms-using-
visual-basicnet-michael-mcmillan-979684
Data Structures And Algorithms Using Java William Mcallister

https://ebookbell.com/product/data-structures-and-algorithms-using-
java-william-mcallister-10680262

Data Structures And Algorithms Using C Ananda Rao Akepogu Radhika Raju
Palagiri

https://ebookbell.com/product/data-structures-and-algorithms-using-c-
ananda-rao-akepogu-radhika-raju-palagiri-10881314

Data Structures And Algorithms Using Java William Mcallister

https://ebookbell.com/product/data-structures-and-algorithms-using-
java-william-mcallister-231831054

A Practical Guide To Data Structures And Algorithms Using Java Sally


Goldman Ken Goldman

https://ebookbell.com/product/a-practical-guide-to-data-structures-
and-algorithms-using-java-sally-goldman-ken-goldman-38204458

Problem Solving In Data Structures And Algorithms Using Java Hemant


Jain

https://ebookbell.com/product/problem-solving-in-data-structures-and-
algorithms-using-java-hemant-jain-53683798
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
26 CHAPTER 1 Abstract Data Types

avoid the use of tuples when storing structured data since it’s better practice to
use classes with named fields. Thus, we define the StudentRecord class
class StudentRecord :
def __init__( self ):
self.idNum = 0
self.firstName = None
self.lastName = None
self.classCode = 0
self.gpa = 0.0

to store the data related to an individual student. You may notice there is only a
constructor with no additional methods. This is a complete class as defined and
represents a storage class. The constructor is all that’s needed to define the two
data fields for storing the two component values.
Storage classes should be defined within the same module as the class with
which they will be used. For this application, the StudentRecord class is defined
at the end of the studentfile.py module. Some storage classes may be intended
for internal use by a specific class and not meant to be accessed from outside the
module. In those cases, the name of the storage class will begin with a single
underscore, which flags it as being private to the module in which it’s defined.
The StudentRecord class, however, has not been defined as being private to the
module since instances of the storage class are not confined to the ADT but in-
stead are returned to the client code by methods of the StudentFileReader class.
The storage class can be imported along with the StudentFileReader class when
needed.
You will note the data fields in the storage class are public (by our notation)
since their names do not begin with an underscore as they have been in other
classes presented earlier. The reason we do not include a restrictive interface for
accessing the data fields is that storage objects are meant to be used exclusively
for storing data and not as an instance of some abstract data type. Given their
limited use, we access the data fields directly as needed.

1.5.2 Implementation
The implementation of the Student File Reader ADT does not require a data
structure since it does not store data but instead extracts data from an external
source. The ADT has to be implemented to extract data based on the format in
which the data is stored. For this example, we are going to extract the data from

Python Tuples. The tuple can be used to store structured data, with
!
CAUTION

each element corresponding to an individual data field. This is not


good practice, however, since the elements are not named and you would
have to remember what piece of data is stored in each element. A better
practice is to use objects with named data fields. In this book, we limit the
use of tuples for returning multiple values from methods and functions.
1.5 Application: Student Records 27

a text file in which the records are listed one after the other. The five fields of the
record are each stored on a separate line. The first line contains the id number,
the second and third contain the first and last names, the fourth line contains
the classification code, and the grade point average follows on the fifth line. The
following text block illustrates the format for a file containing two records:

10015
John
Smith
2
3.01
10334
Jane
Roberts
4
3.81

Listing 1.6 provides the implementation of the ADT for extracting the records
from the text file in the given format. The constructor simply initializes an instance
of the class by creating two attributes, one to store the name the text file and the
other to store a reference to the file object after it’s opened. The open() method
is responsible for opening the input file using the name saved in the constructor.
The resulting file object is saved in the inputFile attribute so it can be used in
the other methods. After the records are extracted, the file is closed by calling the
close() method.

Listing 1.6 The studentfile.py module.

1 # Implementation of the StudentFileReader ADT using a text file as the


2 # input source in which each field is stored on a separate line.
3
4 class StudentFileReader :
5 # Create a new student reader instance.
6 def __init__( self, inputSrc ):
7 self._inputSrc = inputSrc
8 self._inputFile = None
9
10 # Open a connection to the input file.
11 def open( self ):
12 self._inputFile = open( self._inputSrc, "r" )
13
14 # Close the connection to the input file.
15 def close( self ):
16 self._inputFile.close()
17 self._inputFile = None
18
19 # Extract all student records and store them in a list.
20 def fetchAll( self ):
21 theRecords = list()
22 student = self.fetchRecord()
(Listing Continued)
28 CHAPTER 1 Abstract Data Types

Listing 1.6 Continued . . .


23 while student != None :
24 theRecords.append( student )
25 student = self.fetchRecord()
26 return theRecords
27
28 # Extract the next student record from the file.
29 def fetchRecord( self ):
30 # Read the first line of the record.
31 line = self._inputFile.readline()
32 if line == "" :
33 return None
34
35 # If there is another record, create a storage object and fill it.
36 student = StudentRecord()
37 student.idNum = int( line )
38 student.firstName = self._inputFile.readline().rstrip()
39 student.lastName = self._inputFile.readline().rstrip()
40 student.classCode = int( self._inputFile.readline() )
41 student.gpa = float( self._inputFile.readline() )
42 return student
43
44 # Storage class used for an individual student record.
45 class StudentRecord :
46 def __init__( self ):
47 self.idNum = 0
48 self.firstName = None
49 self.lastName = None
50 self.classCode = 0
51 self.gpa = 0.0

The fetchAll() method, at lines 20–26, is a simple event-controlled loop that


builds and returns a list of StudentRecord objects. This is done by repeatedly
calling the fetchRecord() method. Thus, the actual extraction of a record from
the text file is handled by the fetchRecord() method, as shown in lines 29–42.
To extract the student records from a file in which the data is stored in a different
format, we need only modify this method to accommodate the new format.
The Student File Reader ADT provides a framework that can be used to extract
any type of records from a text file. The only change required would be in the
fetchRecord() method to create the appropriate storage object and to extract
the data from the file in the given format.

Exercises
1.1 Complete the partial implementation of the Date class by implementing the
remaining methods: monthName(), isLeapYear(), numDays(), advanceBy(),
Programming Projects 29

and isValidGregorian(). The isValidGregorian() method should deter-


mine if the three components of the given Gregorian date are valid.

1.2 Add additional operations to the Date class:

(a) dayOfWeekName(): returns a string containing the name of the day.


(b) dayOfYear(): returns an integer indicating the day of the year. For ex-
ample, the first day of February is day 32 of the year.
(c) isWeekday(): determines if the date is a weekday.
(d) isEquinox(): determines if the date is the spring or autumn equinox.
(e) isSolstice(): determines if the date is the summer or winter solstice.
(f) asGregorian(divchar = '/'): similar to the str() method but uses
the optional argument divchar as the dividing character between the three
components of the Gregorian date.

1.3 Implement a function named printCalendar() that accepts a Date object


and prints a calendar for the month of the given date. For example, if the
Date object passed to the function contained the date 11/5/2007, the function
should print

November 2007
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

1.4 Modify the Date() constructor to make each of the three arguments optional,
with an initial value of zero. When no argument is supplied to the constructor,
the object should be initialized to the current date. Hint: You will need to
use Python’s date() function from the time.py module.

Programming Projects
1.1 A click counter is a small hand-held device that contains a push button and
a count display. To increment the counter, the button is pushed and the new
count shows in the display. Clicker counters also contain a button that can be
pressed to reset the counter to zero. Design and implement the Counter ADT
that functions as a hand-held clicker.

1.2 A Grab Bag ADT is similar to the Bag ADT with one difference. A grab
bag does not have a remove() operation, but in place of it has a grabItem()
operation, which allows for the random removal of an item from the bag.
Implement the Grab Bag ADT.
30 CHAPTER 1 Abstract Data Types

1.3 A Counting Bag ADT is just like the Bag ADT but includes the numOf(item)
operation, which returns the number of occurrences of the given item in the
bag. Implement the Counting Bag ADT and defend your selection of data
structure.

1.4 The use of the Student File Reader ADT makes it easy to extract student
records from a text file no matter the format used to store the data. Implement
a new version of the ADT to extract the data from a text file in which each
record is stored on a separate line and the individual fields are separated by
commas. For example, the following illustrates the format of a sample file
containing three student records:

10015, John, Smith, 2, 3.01


10334, Jane, Roberts, 4, 3.81
10208, Patrick, Green, 1, 3.95

1.5 In the chapter, we defined and implemented the Student File Reader ADT for
extracting student records from an external source. We can define and use a
similar ADT for output.

(a) Design a Student File Writer ADT that can be used to display, or store to
an output device, student records contained in a StudentRecord object.
(b) Provide an implementation of your ADT to output the records by display-
ing them to the terminal in a neatly formatted fashion.
(c) Provide an implementation of your ADT to output the records to a text
file using the same format described in the text.
(d) Design and implement a complete program that extracts student records
from a text file, sorts them by either student id or student name, and
displays them to the terminal using your ADT. The choice of sort keys
should be extracted from the user.

1.6 We can use a Time ADT to represent the time of day, for any 24-hour period,
as the number of seconds that have elapsed since midnight. Given the following
list of operations, implement the Time ADT.
 Time( hours, minutes, seconds ): Creates a new Time instance and ini-
tializes it with the given time.
 hour(): Returns the hour part of the time.
 minutes(): Returns the minutes part of the time.
 seconds(): Returns the seconds part of the time.
 numSeconds( otherTime ): Returns the number of seconds as a positive
integer between this time and the otherTime.
 isAM(): Determines if this time is ante meridiem or before midday (at or
before 12 o’clock noon).
Exploring the Variety of Random
Documents with Different Content
The Project Gutenberg eBook of An Address to
Free Coloured Americans
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.

Title: An Address to Free Coloured Americans

Author: Anti-slavery Convention of American Women

Release date: September 19, 2012 [eBook #40799]


Most recently updated: October 23, 2024

Language: English

Credits: Produced by Jonathan Ingram, Ernest Schaal, and the


Online
Distributed Proofreading Team at http://www.pgdp.net
(This
file was produced from images generously made available
by The Internet Archive)

*** START OF THE PROJECT GUTENBERG EBOOK AN ADDRESS TO


FREE COLOURED AMERICANS ***
AN ADDRESS
TO
FREE COLORED AMERICANS.
ISSUED BY AN ANTI-SLAVERY CONVENTION OF
AMERICAN WOMEN,
Held in the City of New-York, by adjournments from 9th to 12th May,
1837.

NEW-YORK:
PRINTED BY WILLIAM S. DORR,
123 FULTON STREET.

1837.
AN ADDRESS
TO
FREE COLORED AMERICANS.
Beloved Brethren and Sisters—

The sympathy we feel for our oppressed fellow-citizens who are


enslaved in these United States, has called us together, to devise by
mutual conference the best means for bringing our guilty country to
a sense of her transgressions; and to implore the God of the
oppressed to guide and bless our labors on behalf of our
"countrymen in chains."

All of us have some idea what slavery is: we have formed some
faint conceptions of the horrors of a system based on irresponsible
power, violence, and injustice; but to know what slavery is, we must
see it worked out in practice—we must see the heart-strings severed
one by one, and witness all the refinement of cruelty which is
exercised on the body, soul, and mind of the enslaved. "Let any man
of feeling," says a Southern gentleman, "cast his thoughts over this
land of slavery, think of the nakedness of some, the hungry
yearnings of others, the wailings and wo, the bloody cut of the keen
lash, and the frightful scream that rends the very skies—and all this
to gratify lust, pride, avarice, and other depraved feelings of the
human heart. THE WORST IS NOT GENERALLY KNOWN. Were all the
miseries and horrors of slavery to burst at once into view, a peal of
seven-fold thunder could scarce strike greater alarm." (Swain's
Address, 1830.)

We can readily believe this testimony to the physical sufferings of


the slave: we apprehend these most easily, because all of us are
alive to bodily pain, whilst few comparatively appreciate the mental
and spiritual degradation to which our oppressed brethren are
subjected; yet this is the most appalling feature of American
bondage. Slavery seizes a rational and immortal being crowned by
Jehovah with glory and honor, and drags him down to a level with
the beasts that perish. It makes him a thing, a chattel personal, a
machine to be used to all intents and purposes for the benefit of
another, without reference to the good, the happiness, or the wishes
of the man himself. It introduces violence and disorder, where God
established harmony and peace. It would annihilate the individual
worth and responsibility conferred upon man by his Creator. It
deprives him of the power of self-improvement, to which he is bound
by the unchangeable laws of his Maker. It prevents him from
laboring in a sphere to which his capacities are adapted. It
abrogates the seventh commandment, by annulling the obligations
of marriage, and obliging the slaves to live in a state of promiscuous
intercourse, concubinage, and adultery; thus setting at nought an
institution established by Jehovah himself, and designed to promote
the happiness and virtue of his creatures. It dooms its victims to
ignorance, and consequently to vice. "I think I may safely assert,"
says Mr. Moore, "that ignorance is the inseparable companion of
slavery, and that the desire of freedom is the inevitable consequence
of implanting in the human mind any useful degree of intelligence: it
is therefore the policy of the master that the ignorance of his slaves
should be as profound as possible; and such a state of ignorance is
wholly incompatible with the existence of any moral principles or
exalted feeling in the breast of the slave. (Speech of Mr. Moore,
House of Delegates, Va., 1832.)

"How horrible must be that system which demands as the


necessary condition of its existence, that knowledge should be shut
out from the minds of those who live under it—that they should be
reduced as nearly as possible to the level of brutes, or living
machines—that the powers of their souls should be crushed! Let
each one of us ask, Can such a system be aided, or even tolerated,
without deep criminality?" (Ad. to the Pres. of Ken. by a committee
of the synod of Kentucky.)
But even if slavery could be divested of all its horrible
accompaniments, its ignorance, licentiousness, and other nameless
abominations, we should still regard the circumstance of man
holding his brother man as property as one of the blackest crimes
which corrupt human nature ever invented. Mr. Moore, in the speech
from which we have already quoted, is compelled to acknowledge
the iniquity of this system. "It cannot be denied," he says, "as a
general principle, that it is an act of tyranny, injustice, and
oppression, to hold any part of the human race in bondage against
their consent.... The right to the enjoyment of liberty is one of those
perfect, inherent, and inalienable rights which pertain to the whole
human race, and of which they can never be divested, except by an
act of gross injustice." If we would rightly estimate the wretchedness
in which the perpetration of this "act of gross injustice" has involved
one sixth part of the population of Republican America, we must
compare the condition of our slaves with that of the freemen of their
own age and country. "Things are estimated by comparison; and the
man who is deprived of every natural, civil, and social right, while all
around him are basking in the sunshine of freedom, must feel the
fangs of slavery much more poignantly than the one who, though
subjected to similar privations, beholds his lot but little below that of
those who surround him." We must not, therefore, compare the
situation of slaves in the United States with that of the slaves of
heathen Greece and Rome, where equal laws never existed, and
where the beams of liberty and Christianity never shone; but to form
a correct judgment of the miseries endured by our slaves, we must
compare them with the laboring class of our population in the free
states, and we may then comprehend the debasing influence of a
system which produces such dreadful results as are exhibited on
almost every Southern plantation, where the lash is the principal, if
not the only stimulus.

You are, dear friends, in a peculiar manner fellow-sufferers with


those who are in bondage; because the whites, having reduced their
colored brethren to slavery, with a cruelty proportioned to their
unjust usurpation of power, have labored to impress on the mind of
the community, the unfounded calumny that the people of color are
unfit for freedom: this assertion is designed, on the part of
slaveholders, as a salve for their consciences, and a plea for the
continuation of slavery, and is used by the adversary of all good for
the diabolical purpose of shielding from merited infamy the system
of American slavery.

Nothing will contribute more to break the bondman's fetters, than


an example of high moral worth, intellectual culture and religious
attainments among the free people of color—living epistles known
and read of all men—a standard of exalted piety, of dedication to the
works of righteousness, of humble-mindedness, of Christian charity;
to which abolitionists may confidently point, and ask those who are
forging the manacles of hopeless servitude for our countrymen, what
they can answer to the Judge of all the earth for thus robbing him of
his immortal creatures; and demand of them, in view of what their
slaves might be, to restore their victims to themselves, to the human
family, and to God.

We know, and we rejoice in the knowledge, that the gift of


intellect is co-extensive with the human race, and that our brethren
and sisters, who are writhing under the lash of worse than Egyptian
taskmasters—whose minds are beclouded by ignorance and
enfeebled by suffering, need only to have the same advantages
which Europeans and their descendants have enjoyed, triumphantly
to refute the unfounded calumny that they are inferior in the powers
of intellect, and less susceptible of mental improvement. We
maintain, that the people of color are not in any respect inferior to
the white man, and that under favorable circumstances they would
rise again to the rank they formerly held.

The everlasting architecture of Africa still exists—the wonder of


the world, though in ruins: her mighty kingdoms have yet their
record in history; she has poured forth her heroes on the field, given
bishops to the church, and martyrs to the fires. And for African
physiognomy, as though that should shut out the light of intellect, go
to your national museum, contemplate the features of the colossal
head of Memnon, and the statues of the divinities on which the
ancient Africans impressed their own forms, and there see, in close
resemblance to their features, the mould of those countenances
which once beheld as the creatures of their own immortal genius the
noblest and most stupendous monuments of human skill, and taste,
and grandeur. In the imperishable porphyry and granite, is the
unfounded and pitiful slander publicly and before all the world
refuted: there we see the African under cultivation. If he now
presents a different aspect, cultivation is wanting—that solves the
whole case: for, even now, where education has been expended
upon the pure and undoubted descendants of Africans, it has never
been bestowed in vain. Modern times have witnessed, in their
persons, Generals, Physicians, Philosophers, Linguists, Poets,
Mathematicians, and Merchants—all eminent in their attainments,
energetic in enterprise, and honorable in character; and the Mission
schools in the West Indies exhibit a quickness of intellect, and a
thirst for learning, to which the schools of this country do not always
afford a parallel." (Sermon by Richard Watson, pp. 7, 8, Butterworth,
1824.)

Sacred history bears ample testimony to the learning of the


Egyptians. "Solomon's wisdom excelled the wisdom of all the
children of the East country and all the wisdom of Egypt." Even in
our own country, under the oppressive system which slavery and
prejudice have reared to crush the people of color, the superiority
which occasionally shines out, notwithstanding all the disabilities by
which we have surrounded them, proves beyond dispute that they
are the gifted children of our Heavenly Father. In proof of this, we
shall adduce from numerous testimonies, that of F. A. Sayre, for nine
years a teacher of one of the public schools in Cincinnati.

"Facts have been developed in the progress of the day schools


and Sunday schools here, which have made me believe that the
colored people are not only equal to white people in natural capacity
to be taught, but that they exceed them: they do not receive
instruction; they seize it as a person who has long been famishing
for food—seize the smallest crumb."

I several times visited the different schools for colored children


and have always been gratified to observe the good order and
attention to study which the pupils manifest, and particularly with
the affection with which they regard their teachers. I have, however,
known more particularly the school for boys which brother W——
teaches, there I have seen boys of from 9 to 12 years of age, who
had learned the alphabet within a year, who were able to exhibit to
advantage, in reading and spelling, to write legibly, to recite long
lessons in History, which they had been a short time studying, and to
undergo an examination in Arithmetic, which when I first witnessed
it, perfectly astonished me. I have taught common schools for about
15 years at intervals, and have visited many taught by others, and I
must candidly say, that I have never been acquainted with one
which for rapid progress in the different studies pursued, and for the
interests manifested by the pupils could be compared with this, nor
have I ever seen so much good feeling in the intercourse of teacher
and pupils."

And, in corroboration of the above position, we shall mention a


few out of many instances in which persons of color have
surmounted every obstacle to mental and moral improvement.
James Derham, who was originally a slave, was skilled in the
languages, and became the most distinguished Physician at New
Orleans. Dr. Rush, of Philadelphia, says, "I conversed with him, and
found him very learned: I thought I could give him information
concerning the treatment of diseases, but I learned more from him
than he could expect from me." Benjamin Bannaker was a slave in
Maryland: he obtained his freedom, and removed to Philadelphia.
Without any encouragement but his passion for acquiring
knowledge, and with no other books than the works of Ferguson and
the tables of Tobias Mayer, he applied himself to the study of
Astronomy. In 1794 and '95, he published Almanacs at Philadelphia,
in which are calculated and exhibited the different aspects of the
planets, a table of the motions of the sun and moon, their risings
and sittings, and the courses of the bodies of the planetary system.
Bannaker sent his Almanac in manuscript to Thomas Jefferson,
previous to its publication, accompanied by a long and interesting
letter on the condition of his brethren; and the following extracts are
taken from Jefferson's reply:—"Sir, I thank you sincerely for your
letter, and for the Almanac it contained. Nobody wishes more than I
do, to see such proofs as you exhibit, that nature has given to our
black brethren talents equal to those of the other colors of men; and
that the appearance of the want of them is owing merely to the
degraded condition of their existence, both in Africa and America. I
have taken the liberty of sending your Almanac to Monsieur de
Condorcet, Secretary of the Academy of Sciences at Paris, and
Member of the Philanthropic Society, because I considered it a
document to which your whole color had a right for their justification
against the opinions which have been entertained of them." A late
West India paper mentions the death of Mr. Watkis, a colored lawyer
in Jamaica, "by which the bar was deprived of one of its brightest
ornaments." In the Island of St. Kitts, the proportion of colored
members is increasing every year, and several of the special
magistrates are colored men. The Editor of the St. Christopher
Weekly Intelligencer and Advertiser is a colored man, who has been
a bold advocate of liberal principles. He is described as a thorn in the
side of the planters, and a great blessing to the Island. And in the
United States of America, there are men and women now living
whose talents, piety, and worth, are undeniable.

If we contemplate the moral character of the colored man we


shall meet with even more frequent demonstrations of the kind care
of our beneficent Creator who hath made of one blood all nations,
and bestowed upon his rational creatures those qualities of the heart
which are the brightest ornament of human nature. "In maternal,
filial and fraternal affections," says Wadstrom, "I scruple not to
pronounce them superior to any Europeans I was ever among." "Of
all the people I have ever met I think they are the kindest, they will
let none of their people want for victuals, they will lend and not look
for it again, they will even lend clothes to each other if they want to
go any where, if strangers come to them they will give them victuals
for nothing, they will go out of their beds that strangers may sleep in
them."—We not unfrequently have the evidence of slaveholders
themselves to the faithfulness and tender attachment of their slaves.
In a sermon preached by George W. Freeman, Rector of Christ
Church, Raleigh, North Carolina, in which he endeavors to prove that
slavery is a Bible institution we find the following testimony to the
moral worth of those whom he calls a different race of men." "To
many of our servants, to them who serve us faithfully, who are ever
attentive to our wants, who cheerfully fulfil our commands, who
labor abroad for us when we are in health, and who come at our call
to nurse us in our sickness, and who, laying aside, as it were, all
regard to their own comforts, submit without murmuring, or
impatience to the most wearying and exhausting of all employments,
complying with our most unreasonable whims, and meekly bearing
with our fretfulness and caprices; to them, and I must do this class
of people the justice to say there are many such among us—to such
of our domestics as these we surely owe a debt of gratitude, which
all our kindliest acts, should we even live beyond the age of man
would scarce suffice to discharge.

Noble instances are recorded of their self-denial and liberality.


—"Jasmin Thoumazeau was born in Africa, brought to St. Domingo
and sold for a slave when he was 22 years of age, but afterwards
obtaining his freedom he established a Hospital at the Cape, in 1756
for poor persons of color. More than forty years were devoted by
himself and his wife to this benevolent institution, and his fortune
was subservient to their wants. The only regret they felt, while their
time and substance was devoted to these destitute objects, arose
from a fear that after they were gone the Hospital might be
abandoned." Joseph Rachel, a trader, who resided in the island of
Barbadoes went to a man who had lost his property and to whom in
the early part of his life he owed some obligations and gave him the
fragment of his burnt bond for £60 and his discharged account for a
considerable sum, telling him he was sensibly affected with his
misfortunes and releasing him from all obligation to pay the debts.
The philanthropists of England take pleasure in speaking of him.
Having become rich by commerce, he consecrated all his fortune to
acts of benevolence. The unfortunate without DISTINCTION OF
COLOR had a claim on his affections. He gave to the indigent, lent to
those who could not make a return—visited prisoners, gave them
good advice and endeavored to bring back the guilty to virtue." Two
slaves in New Orleans who by industry and economy had purchased
their freedom and laid up about $400, bought with their earnings the
freedom of another slave.—One day as the wife was sitting in the
door of her cottage she said to herself "I have so much money and if
I can make it the instrument of redeeming one of my fellow-beings
from slavery, then I can say to my soul 'depart in peace.' She
accordingly purchased one for $250 and in order to place her in a
situation where she would hear the gospel preached, she brought
her to the city of New-York. A more noble instance of genuine
benevolence does not adorn the annals of philanthropy than is
exhibited in this illiterate daughter of Africa, who gave nearly her all
to redeem one captive sister. We have in this city a colored sister
well known and beloved who by the labor of her own hands has
ransomed eleven slaves.—But for her they would probably have
dragged out their lives in hopeless bondage.—Her "witness is in
heaven, her record is on high. [1] Similar accounts might be
multiplied but enough has been said to prove to any candid mind the
truth of our position, we will therefore only add the testimony of
some of our Southern sisters who affirm that they have known
slaves of exalted piety, high intelligence and warm affections, who
under circumstances the most trying have exhibited a degree of
practical Christianity they have rarely witnessed.

[1] In citing these instances of benevolence we wish it


understood, that while we approve of redeeming a captive from
bondage, we utterly deny the right of the master to sell or hold
the slave as property, just as we deny the right of the Corsair to
the persons of his prisoners, or the ransom which may be offered
for their redemption.

We cannot forbear mentioning in connection with this subject the


noble example which the colored slaveholders of Martinique have set
to their white brethren by petitioning the French Chamber of
Deputies to abolish slavery in that island, stating that they regarded
it as an act not only of justice but of policy.—This is the only record
on the page of history of such an act of mercy but we hope it may
stimulate slaveholders in these United States to petition Congress to
exert her influence in destroying the horrible system of American
Slavery by abolishing it in the District of Columbia and in Florida, and
by exterminating the interstate slave trade.

We earnestly entreat you to emulate the conduct of your brethren


in Martinique by letting your righteousness exceed the righteousness
of our white fellow-citizens. "That whereas they speak evil against
you as evil doers, they may by your good works which they shall
behold glorify God. For so is the will of God that with well doing ye
may put to silence the ignorance of foolish men." Your situation is in
some respects more favorable to the growth of piety than that of the
whites, you are in the furnace of affliction, and adversity has a much
more salutary influence on the mind than prosperity. We believe that
our Almighty Father has permitted your unparallelled sufferings,
because he designs to bring you up to his assistance in regenerating
our guilty country—he has been at infinite pains to refine you as
silver is refined, that you may reflect more perfectly in your conduct
and conversation the image of Jesus Christ. "Beloved think it not
strange concerning the fiery trial which is to try you, as though some
strange thing happened unto you, but rejoice in as much as ye are
partakers of Christ's sufferings." You have the advantage of standing
aloof from the political chicanery and wickedness which seem
inseparable from public life, you are shielded from many of those
temptations which encircle the fashionable world, and in a measure
from the love of money, which is the root of all evil, because the
acquisition of wealth is not with you as with your paler brethren, the
certain means of worldly distinction. You may examine with a
philosophic and impartial eye, the baneful effect of all these
influences upon our white population, and as you rise from under
the unhallowed prejudice which now crushes you to the earth,
remember the solemn responsibilities which rest upon you and keep
yourselves unspotted from the world, that your praise may be of God
and not of men.

With deep regret we have heard that some of our colored


brethren and sisters in our great cities frequent the theatre. This is a
sink of vice from which we earnestly beseech you to keep yourselves
entirely separate. Let the language of every one amongst you be,
"Oh my soul, come not thou into their secret, unto their assembly
mine honor, be not thou united." Sometimes in these scenic
representations, your "countrymen in chains" are held up to the
scorn and derision of an unfeeling multitude; the poor slave is
introduced to be the object of heartless mirth. Can any colored man
or woman voluntarily witness these dreadful pictures of the
degradation of their brethren, and does not your presence identify
you with the oppressors, who thus wantonly hold up to public
contempt those whom they have first debased, and then despised.

Permit us to offer you a few remarks on the subject of personal


decoration—this is a snare which Satan still triumphantly lays, even
for professing Christians who indulge in fashionable and extravagant
apparel, forgetful of the apostolic injunction, "Let your adorning not
be that outward adorning, of plaiting the hair, and of wearing of
gold, or of putting on of apparel; but let it be the hidden man of the
heart, in that which is not corruptible, even the ornament of a meek
and quiet spirit, which is in the sight of God of great price." Our
hearts have been comforted in our intercourse with you, by
observing that there is little gaudy or superfluous dress to be seen,
in such places of worship as we have visited; we regard it as one
evidence of the purity of your morals, and your just sense of that
decorum which ought to characterise every Christian assembly. A
Christian legislator has said that the trappings of the vain world
would clothe the naked, and we affectionately entreat you to
cultivate such a sense of your accountability to God, and the
allegiance you owe to Him, that your dress may be such as becomes
men and women professing godliness. To you this branch of religious
duty is of double importance. A large proportion of you are obliged
to obtain a subsistence by your daily labor; some of you are filling
the responsible office of teachers, and it is of great consequence
that you expend in the most judicious and profitable manner what is
thus hardly earned, and that you set an example of Christian
moderation and simplicity to your companions and your pupils.

Another reason for the practice of Christian economy in all your


expenditures, is, that extravagance either in living or in apparel, has
a deleterious influence on the poorer classes of our community, both
colored and white; it draws a line of division between the rich and
the poor, which is destructive of that equality, that sweet fellowship
of feeling, which God designed should exist among his creatures; it
creates factitious distinctions in society, which are utterly at variance
with the law of love that Christ gave as a governing principle to his
disciples. When he designed to do us good, he took upon himself
the form of a servant—surely we should love and honor this office.
He took his station at the bottom of society, He voluntarily identified
himself with the poor and the despised, He manifested a peculiar
interest in those classes which we are wont to treat as our inferiors,
because He designed to elevate them, to give a moral impulse to
their character, and to make them new creatures. He wanted them
to behold in Him a model to imitate, as well as to give them the
unspeakable advantage of mingling with Him in near and intimate
communion. This was no doubt a powerful incentive to them to
emulate their divine friend, and render themselves worthy
companions of the Lord Jesus. None of us can stoop as low as our
Saviour did, because the same infinite distance cannot exist between
created beings; but we may as far as our frailty admits, imitate His
blessed example; we may like Him, make ourselves of no reputation;
we may, like Him, sit down at the table of the despised publican and
sinner, and cheer the abodes of the humble and the poor by our
presence and our love. This interchange of social visits, this meeting
together as suppliants at a throne of grace, will form a bond of
union stronger than any that can exist, while the rich and the
educated stand at a distance from the poor, and invite them to come
up, without advancing near enough to stretch forth the hand to
assist their efforts. Our minds are solemnly impressed with the
necessity of practising this duty, both among the colored and white
population, and it would gladden our hearts to see you taking the
lead in this Christ-like enterprise. We are persuaded that if we would
labor effectually for the moral and intellectual elevation of the poor,
we must condescend to men of low estate; we must identify
ourselves with them, and place ourselves on their level; we must, by
our example as well as our precepts, teach them that moral worth is
our standard of excellence, and that we are living in the practical
acknowledgement of that sublime precept "One is your master, even
Christ, and all ye are brethren." Whilst we press this duty upon our
colored brethren and sisters, we feel that it is equally incumbent
upon all, and desire through divine assistance to be strengthened to
perform it.

We wish also to suggest the importance of cultivating the virtue


of personal and domestic neatness; we believe it contributes
essentially to the purity of the heart, and that attention to the
neatness of our persons, and the order of our habitations, has a
happy influence on the temper and the understanding, as well as the
morals. We are aware that it is often difficult, where necessity
compels us to use one apartment for every purpose, to preserve that
order and cleanliness which is desirable, but we believe where the
wish prevails, much may be accomplished, even in very unfavorable
circumstances. Many of you sustain the relations of servants in
families; this places you in a very responsible situation, because it
brings you under the daily observation of those, who have been
educated with deep-rooted prejudices against you, and it affords the
best opportunity of proving that these prejudices are as unfounded,
as they are unjust—of exhibiting in your deportment, that moral
loveliness which will constrain those who regard themselves as your
superiors, to acknowledge that worth can neither be determined by
the color of the skin, nor by the station occupied. You have it in your
power, by a faithful and conscientious discharge of your duties, to
secure the highest wages for your services, and by a prudent and
economical use of those wages, to obtain for your children, if not for
yourselves, the blessing of a good education, but we affectionately
exhort you not to enter into any engagements as domestics, which
will deprive you of the privilege of reading the Scriptures, and
attending a place of worship, this being a duty which is imperatively
called for as an evidence of our allegiance to the King of kings.
Carefully avoid families which pay little or no respect to the Sabbath,
that you may escape the contamination arising from such
intercourse. We have regretted seeing so many of our colored
friends engaged as servants in hotels and steam-boats; these places
are not calculated to cherish moral and religious feeling, and they
afford few facilities for the cultivation of the mind. Agricultural
pursuits would contribute more to independence and elevation of
character, and however much we may be disposed to aid you, it will
be after all by your own exertions that you will rise to that situation
in society, which we desire to see you occupy.

The establishment of good schools is another very important


means of aiding in the great work of moral and intellectual elevation;
to promote this object every exertion should be made. On the rising
generation depends in a great measure the success of that
enterprise, which aims at establishing Christian and Republican
equality among the citizens of these United States. Let us then labor
to implant in the minds of our children a love for useful learning, to
imbue them thoroughly with religious feeling, to train them to habits
of thinking, of industry and economy, to lead them to the
contemplation of noble and benevolent objects, that they may
regard themselves as responsible beings upon whom high and holy
duties devolve. Let them come up to the help of the Lord in the
mighty work in which we are engaged, prepared by education and
enlightened piety to aid in the great moral conflict between light and
darkness, which now agitates our guilty country. Anti-Slavery
Societies, embracing in their Constitutions, abstinence from slave
labor products, as far as this can be done. Peace Societies, based on
the principle that all war is inconsistent with the gospel. Temperance
Societies, on the principle of abstinence from all that can intoxicate,
and Moral Reform Societies should be organized throughout our land
wherever it is practicable. The formation of Maternal Associations,
Dorcas Societies, Reading & Conversation Companies, and above all,
Meetings for Prayer will have a salutary influence in combining
efforts for improvement. Whenever you can unite with white
associations, it will be productive of reciprocal benefit, because it will
tend to remove that unchristian prejudice which "bites like a serpent,
and stings like an adder." You may have to suffer much in thus
commingling, but we entreat you to bear hardness as good soldiers
of Jesus Christ, that your children, and your children's children, may
be spared the anguish you are compelled to endure on this account.
To carry forward these various schemes of elevation and
improvement, money is absolutely requisite, and if all that is saved
from unnecessary expenses be lent to the Lord to advance the great
work of Reformation, as well as devoted to charitable purposes it will
be treasure laid up in heaven, which neither moth nor rust can
corrupt.

Another subject which is worthy of your consideration is the


consistency of abstaining, as Abolitionists, from the use of slave
labor products, as far as is practicable. The conviction that this is a
duty, is gaining ground among the friends of emancipation, and we
doubt not that the self-denial which it will probably demand on our
part, will arouse the conscience of the slaveholder, by demonstrating
that we are willing to sacrifice interest and convenience to principle.
To the toil-worn slave, it will minister unspeakable consolation, to
hear, while bending over the rice, or sugar, or cotton field, and
writhing under the lash, that his friends at the North feel a sympathy
so deep for his sufferings, that they cannot partake of the proceeds
of his unrequited toil. Think you not it would cheer his agonized
heart, and impart renewed strength to endure his affliction, to know
that his blood was not spilt for the gratification of those who are
trying to obtain for him the blessing of liberty. We entreat you to
give this evidence of your love to those who have emphatically fallen
among thieves, then, although you cannot pour the wine and the oil
into their corporeal wounds, nor dress with mollifying ointment, the
bloody gash of the drivers' whip, you may minister to their mental
comfort, and soothe their broken hearts. Let it not be imagined that
the slaves of the South are destitute of intelligence, or ignorant of
what is doing at the North; many a noble mind is writhing there in
bondage, and panting for deliverance, as the hart panteth after the
water brooks. Mr. Goode, in the legislature of Virginia in 1832, when
he brought in the resolution which produced the celebrated debate
in that body, "earnestly pressed upon the House, the effect of what
was passing upon the minds of the slaves themselves. Many of them
he represented as wise and intelligent men, constantly engaged in
reflection, informed of all that was occurring, and having their
attention fixed upon the Legislature." And we have been informed on
good authority, that a slave in one of the Southern states, one of
those whose soul never bowed to the yoke of bondage, said, that
himself and his fellow sufferers spent many a midnight hour in
discussing the probable results of the abolition movements, and
were firmly persuaded that their redemption from bondage would
finally be effected, though they knew not exactly by what means it
would be accomplished. Every fugitive slave who is carried back,
bears to his unhappy countrymen an account of all that is doing.
Every freeman who falls into the ruthless fangs of the kidnapper,
spreads information at the South, of all our efforts for the abolition
of slavery, and we put it to any one of ourselves, whether, if we
were wasting our energies, and toiling in cheerless bondage, it
would not be some alleviation to know, that there were those who
loved us so tenderly, and felt for us so keenly, that they would not
participate in the luxuries which were the fruit of our extorted and
unrequited labor.

It has been urged, and with some plausibility, that the use of the
products of slave labor, is one of the "little things" connected with
the great cause of abolition. Admitting it to be little, is it therefore
unimportant? Does not the reproof of our Redeemer exactly apply to
this case, when in speaking of the tithe of mint, annise and cummin,
and the weightier matters of the law, he says, "This ought ye to
have done, and not to leave the other undone;" but however small it
may appear, it involves a great principle, because it really
encourages the traffic in human flesh, by offering to the slaveholder
an inducement to perpetuate the system of oppression from which
he derives his unrighteous gains. Another hackneyed objection is,
that our abstaining will not lessen the quantity grown, and other
consumers will soon be found. With this we have nothing to do; we
might on the same premises, purchase and hold slaves, because if
we do not, others will. No doubt much inconvenience and some
privation must be endured, but this will be continually decreasing, as
West India productions will furnish a substitute. In some instances
the use of cotton cannot perhaps be avoided by the poor, but still
much may be done, and those of us who have made the experiment
can testify that our abstinence has strengthened us for the work we
are engaged in, and that there is a sweet feeling of conscious
integrity that gladdens our hearts. "I will wash mine hands in
innocency, so will I compass thine altar, oh Lord." In proportion as
the demand for free labor products increases, the supply will
increase, and the greater the quantity of such articles which is
thrown into the market, the more their price will lessen. Besides
"allowing the labor of a slave for six years, to produce all the various
slave-grown products which anyone may use during the course of
his life, would not he who was so occupied be in effect the slave of
such an one during the time he was thus employed?" This is a
solemn and affecting consideration, and can be most correctly
weighed when we are on our knees before God; it is a matter
between Him and every individual soul, and he alone can settle it.

We believe it was the want of that principle which we have been


endeavoring to inculcate, "Thou shalt love thy neighbor as thyself,"
that gave birth to the scheme of expatriating our colored brethren to
Africa. We do not design to attribute unhallowed motives to all who
engaged in this crusade against the rights and happiness of free
American citizens; many, we believe, like our beloved brother, Gerrit
Smith, embarked in this enterprise without examining the principles
of the Society, deluded by the false, though plausible assertion, that
the colored man could not rise in his native land to an equality with
his white compatriots, and desirous to do them all the good that
circumstances admitted. Nevertheless, we are constrained to believe
what you have so often asserted, and so keenly felt, that "The
Colonization Society originated in hatred to the free people of color."
We rejoice that you early detected the fallacy and the iniquity of this
scheme; that you arose in the dignity of conscious rights, in the
majesty of moral power, in the boldness of injured innocence, and
exposed the cruelty and unrighteousness of a project, which, had it
been carried fully into execution, would have robbed America of
some of her best and most valuable citizens, and exiled from our
shores, those whose hearts are bound to their country by no
common bonds, even by the holy bonds of sympathy for their
"countrymen in chains." A project which would have poured upon
the shores of Pagan Africa, a broken hearted population, prepared
by mental suffering to sink into a premature grave. A band of exiles,
who had been exposed against their judgment and their will, to all
the nameless trials which belong to the settlement of colonial
establishments, and all that anguish which must have been endured
under the reflection that they had been banished from the land of
their birth, merely to gratify an unhallowed prejudice when their
country needed their services, when there was abundant room in the
land, though not in the hearts of their countrymen. We admire your
noble and uncompromising resistance to this scheme of oppression,
and your children will thank you to the latest generation. We honor
you for the undaunted and generous resolutions which you passed
soon after the Colonization Society came into existence, when the
spontaneous language of your hearts was embodied in the following
sentiments:

"Whereas, our ancestors (not of choice) were the first successful


cultivators of the wilds of America, we their descendants, feel
ourselves entitled to participate in the blessings of her luxuriant soil,
which their blood and sweat manured, and that any measure, or
system of measures, having a tendency to banish us from her
bosom, would not only be cruel, but would be in direct violation of
those principles which have been the boast of this republic.

Resolved, That we view with deep abhorrence the unmerited


stigma attempted to be cast upon the reputation of the free people
of color, by the promoters of this measure, "that they are a
dangerous and useless part of the community." When in the state of
disfranchisement in which they live, in the hour of danger they
ceased to remember their wrongs, and rallied round the standard of
their country.

Resolved, That we will never separate ourselves from the slave


population in this country: they are our brethren by the ties of
consanguinity, of suffering, and of wrong; and we feel that there is
more virtue in suffering privations with them, than enjoying fancied
advantages for a season.

Resolved, That having the strongest confidence in the justice of


God, and in the philanthropy of the free states, we cheerfully submit
our destinies to the guidance of Him who suffers not a sparrow to
fall to the ground without his special Providence."

We praise the Lord, that while the white man slumbered over the
wrongs of his enslaved countrymen, or stretched out his hands to
rivet the bondman's chains, or to thrust his brother from his side,
your sympathy and your compassion, like that of the beneficent
Redeemer, was wakeful and active, and called forth from the depths
of your souls the following soul-stirring appeal. Where, oh! where
were the hearts of Americans, that they responded not to your call?

"We humbly, respectfully, and fervently entreat and beseech your


disapprobation of the plan of colonization now offered by the
"American Society for Colonizing the Free People of Color of the
United States." Here, in the city of Philadelphia, where the voice of
the suffering sons of Africa was first heard—where was first
commenced the work of abolition on which heaven has smiled (for it
could have success only from the great Master); let not a purpose be
assisted which will stay the cause of the entire abolition of slavery in
the United States, and which may defeat it altogether—which
proffers to those who do not ask for them what it calls benefits, but
which they consider injuries—and which must ensure to the
multitude, whose prayers can only reach you through us, misery,
sufferings, and perpetual slavery."

Nor can we pass by unnoticed the noble conduct of our sister in


Ohio, who, when her father proposed to bring her to the North,
where she might pass for a white woman, and settle upon her a
comfortable independence, replied that she would never forsake her
people—that she would rather suffer with them than enjoy all the
advantages he promised. We do homage to the virtue which
preferred to endure affliction with the oppressed, rather than to bask
in the sunshine of worldly prosperity and popular favor.

But for the dignified opposition which you manifested—but for the
developments which you made of the real designs and fearful
consequences of colonization, your guilty country would probably
have added to her manifold transgressions against the descendants
of Africa, the transcendant crime of banishing from her shores those
whom she has deeply injured, and whom she is bound by every law
of justice and of mercy to cherish with peculiar tenderness. But for
your virtuous and uncompromising hostility to the Colonization
Society, a portion of our countrymen might never have been
disabused of the idle and fallacious expectation, that this scheme
would cure the moral evil of slavery, and put an end to the horrible
slave traffic carried on on the coast of Africa. You saw that the root
of the evil was in our own land, and that the expatriation of the best
part of our colored population, so far from abolishing slavery, would
render the condition of the enslaved tenfold more hopeless. You saw
that the only means of destroying the slave trade, was to destroy
the spirit of slavery; and how just have been your conclusions, let
the following testimonies declare—we extract from an official
communication to the secretary of the Navy, by Captain Joseph J.
Nicholson of the Navy:—"The slave trade, within the last three years,
has seriously injured the colony. Not only has it diverted the industry
of the natives, but it has effectually cut off the communication with
the interior. The war parties being in the habit of plundering and
kidnapping for slaves all whom they meet, whether parties to the
war or not, the daring of the slaver increases with the demand for
slaves, which could not of late be supplied by the usual means; and
within a year four slave factories have been established almost
within sight of the Colony."

The following statement is taken from the "Colored American:"—A


vessel arrived at Halifax on the 12th ult., from Kingston, Jamaica,
which reports, that when two days out she fell in with a Spanish
slaver bound to Havana, having four hundred poor wretched beings
on board, in a state of starvation. Forty had died for want of food.
The captain stated that the poor creatures had, during the past
month, subsisted on rice water." Had we not been blinded by
interest and by prejudice, our reason might have taught us that as
long as the republic of the U. S. is a mart where human flesh and
souls of men are bought and sold, so long will European and
American cupidity furnish human merchandise for this detestable
commerce. Thousands of slaves have been introduced into the
United States through the island of Cuba, since the slave trade was
declared piracy by our national legislature. We stand before the
world as a nation of hypocrites, and you are equally concerned, as
American citizens, to labor to bring your country to a sense of her
crimes. You are equally concerned to do all that can be done, to
arrest the progress of the spirit of colonization, which takes our
countrymen from their native land without their consent, by giving
them the cruel alternative of slavery or banishment, breaks up the
tenderest ties of nature and casts them on a foreign soil. And what
is our international slave trade, but compulsory colonization. "There
have been transported—doubtless without their consent—from the
older slave states to Alabama, Mississippi, Louisiana, and Arkansas,
during the year 1836, the enormous number of two hundred and
fifty thousand slaves."—Eman.

We deeply deplore the situation of our free colored citizens in the


slaveholding states, we sympathize in their trials, we know that the
oppressive laws enacted against them are to use the language of a
writer in the Richmond Whig of March 21, 1832, "A code of penal
laws in many respects worthy the temper of Draco, written indeed in
blood.... By this code information to them is proscribed, social
intercourse interdicted, religious worship in most of its forms
prohibited." We know that these unrighteous decrees have driven
many of our Southern brethren to a foreign land in the hope of
finding on the shores of heathen Africa, a degree of liberty,
independence and happiness which they saw no human probability
of enjoying in Christian America, but while we sympathize with them
in their sufferings, of which the free people of color in the non-
slaveholding States largely participate, yet we believe that patient
submission to these cruel inflictions, would have identified their
interests more with that portion of our countrymen who are toiling in
bonds, and would have advanced the cause of emancipation. The
cruel policy of the slaveholder to separate as much as possible the
free people of color from the slaves, to prevent all coalition between
them, to destroy all sympathy of feeling and oneness of interest, has
succeeded but too well—the free colored people of the South stand
by themselves, unacknowledged as men by their haughty superiors,
unknown as brethren by their down-trodden "countrymen in chains,"
a few of them have even been tempted to join hands with the
oppressor and rivet bonds on those for whose deliverance they
should have toiled and wept and prayed. One of the results of this
crafty policy has been, that many have been seduced to abandon
their country and their enslaved brethren, to seek for themselves
and their families an asylum from the oppression of Christian,
Republican, America. These, however unintentionally, have, we
believe, fully answered the designs of the subtle politicians of the
South and have bound more firmly around the quivering limbs of
their kindred the manacles of slavery.—The desertion of such has
added strength to the Colonization interest, and cherished the
insane hope that all our valuable free colored citizens might in time
be transported to Africa. We, therefore, deprecate the departure of
every free colored American, unless impelled by a sense of duty,
because it is injurious to the interests of the slave and contributes to
foster in the bosoms of their white fellow-citizens that prejudice
which Satan created and which he is now using as one of the most
powerful engines to prevent the elevation of the free and the
enfranchisement of the enslaved.

Our brethren and sisters in bondage have their eyes fixed with
the deepest intensity of interest upon their friends in the Northern
States, they are looking unto us as unto "Saviours who shall come
up on Mount Zion" to deliver them out of the hand of the spoiler.
Jehovah has entrusted us with a high and holy commission he has
commanded us to "Defend the poor and fatherless, to do justice to
the afflicted and needy, to deliver the poor and needy; to rid them
out of the hand of the wicked" and we believe God will bless our
efforts in this righteous cause, if we are willing to endure the
reproach, the calumny, the self-denial which is involved in this
Reformation, but beloved friends let us keep ever in mind, that
unless we are men and women of prayer, we shall not be able to
effect what we profess so earnestly to desire, viz., that God would
melt the hearts of the slaveholders thro' the powerful influence of
his Holy Spirit that they may "let their captives go," "not for price nor
reward," but for their own peace sake and because the love of God
is shed abroad in their hearts. When the Redeemer of men was
about to ascend to the bosom of the Father and resume the glory
which he had with Him before the world was, he promised his
disciples that the power of the Holy Ghost should come upon them,
and that they should be witnesses for Him to the uttermost parts of
the earth. What was the effect upon their minds?" "They all
continued with one accord in prayer and supplication with the
women." Stimulated by the confident expectation that Jesus would
fulfil his gracious promise, they poured out their hearts in fervent
supplications, probably for strength to do the work which he had
appointed them unto, for they felt that without Him they could do
nothing and they consecrated themselves on the altar of God, to the
great and glorious enterprize of preaching the unsearchable riches of
Christ to a lost and perishing world. Have we less precious promises
in the Scriptures of Truth, may we not claim of our God the blessing
promised unto those who consider the poor, the Lord will preserve
them and keep them alive and they shall be blessed upon the earth.
Does not the language "Inasmuch as ye did it unto one of the least
of these my brethren, ye did it unto me," belong to all who are
rightly engaged in endeavoring to unloose the bondman's fetters?
Shall we not then do as the Apostles did, shall we not in view of the
two millions of heathen in our very midst, in view of the souls that
are going down in an almost unbroken phalanx to utter perdition,
continue in prayer and supplication that God will grant us the
supplies of his Spirit to prepare us for that work which he has given
us to do. Shall not the wail of the mother as she surrenders her only
child to the grasp of the ruthless kidnapper, or the trader in human
blood, animate our devotions. Shall not the manifold crimes and
horrors of slavery excite more ardent outpourings at the throne of
grace to grant repentance to our guilty country and permit us to aid
in preparing the way for the glorious second Advent of the Messiah,
by preaching deliverance to the captives and the opening of the
prison doors to those who are bound.

But not alone for the down-trodden slave should we be engaged


to labor, our country from Maine to Florida is more or less connected
with, and involved in, the awful sin of slavery, "the blood of the poor
innocents is found in our skirts," the free states are partakers with
those who rob God of his creatures, for although most of them have
nominally no slaves on their soil, they do deliver unto slaveholders
the servant that is escaped from his master, in direct violation of the
command of Jehovah "Hide the outcasts: bewray not him that
wandereth.—Let mine outcasts dwell with thee; be thou a covert to
them from the face of the spoiler."—The unhappy fugitive goaded
almost to madness by oppression finds no resting place for the sole
of his foot until he reaches the icy shores of Canada. An exile from
his native land, because his soul cannot bow down to the unbridled
passions of his fellow-worm; because he nobly dares to take the
freedom which Jehovah gave him with the first inspiration of his vital
breath, because rather than be a slave he braves the storm and
plunges through the flood and suffers hunger and thirst and
nakedness and cold. For thus magnanimously recoiling from unjust
usurpation he is branded as a fugitive, and hunted through our free
states with all the fierceness of savage barbarity, while no measures
are adopted to procure the repeal of these unrighteous decrees. Oh
when in this proud republic God maketh inquisition for blood, when
he remembereth the cry of the humble—where shall we appear? will
not the language be uttered against us "the land is full of blood; the
iniquity is exceeding great, mine eye shall not spare, neither will I
have pity, but I will recompense their way upon their head."

Nor is the church less corrupt than the state, she exhibits now
just such a departure from primitive purity as is described by the
prophet Ezekiel in speaking of the Jewish Church.—"Thou didst trust
in thine own beauty, because of thy renown. Thou hast also taken
thy fair jewels of my gold and my silver which I had given thee, and
madest to thyself images of men, and didst commit whoredom with
them. And tookest thy broidered garments and covered them, and
thou hast set mine oil and mine incense before them." Is it not the
fear and the idolatry of man which makes so many of those who fill
the sacred office of ministers of Jesus Christ stand dumb on the
watch-tower; so many unclose their sacrilegious lips to stigmatize
the God of Love as the founder of the system of American slavery—
what but the deep corruption of the church could tempt her to cast
over this bloody moloch her broidered garment, and try by snatching
a few jewels to adorn her diadem from Ceylon and the Sandwich
Islands, from Burmah, and from the Rocky Mountains, to turn away
the public gaze from the leprosy which consumes her vitals.

Let us not be deceived by the seeming prosperity of our country.


Babylon was filled with gold and with silver, and Belshazzars impious
feast was crowned with wine and luxurious delicacies, yet even then
the hand-writing on the wall was appointed, the doom of that great
empire was decided in the court of heaven, and the irreversible
sentence was soon pronounced upon her haughty monarch, "Thou
hast lifted up thyself, God hath numbered thy kingdom and finished
it." Let us not be deceived by the fair appearances of the church, her
efforts, and her revivals. Slavery is the master sin of our country; it
is twined around the horns of the altar—it is couched beneath the
table on which are laid the sacramental elements—it rises rampant
in our pulpits—its spirit may be seen stalking with unblushing
effrontery through almost every temple of benevolence, every
seminary of learning,[2] every Church of God where the white and
the colored are as carefully separated as though the one was
washed and made white in the blood of the Lamb, and the other
was an unclean thing, whose very touch was contamination. We feel
constrained to enter our solemn protest against this unrighteous
practice in all its forms.—"God has created of ONE BLOOD all the
nations to dwell on all the face of the earth," and whoever
interposes a barrier to their living as brethren, breaks the harmony
which He has established. Let the Church in America deck herself as
she may with the Lord's jewels, so long as she cherishes the Hydra-
headed monster slavery in her bosom, so long will her oblations on
heathen shores be vain, her incense an abomination, her solemn
meetings a mockery. Our souls are drawn out in tender sympathy to
our dear brothers and sisters who are the victims of this cruel
prejudice, may you experience that peace which the world can
neither give nor take away, and rejoice in the promise that the last
shall be first.

[2] We mention as an example worthy of imitation the noble


individuals who took the lead at Lane Seminary in contending for
the rights of our colored citizens, and when their work there was
accomplished, went among their colored brethren and sisters,
and met them as equals bearing the impress of that God who
stampt his image on his creature man. If each of our seminaries
could boast of such champions of Human Rights, our colleges and
schools might soon be regenerated, and our temples of science
be thrown open to all our citizens irrespective of color or
condition.

Let us turn our eyes on God's chosen people and learn a lesson
fraught with fearful instruction.—As the time of their downfall
approached, when for their manifold transgressions they were to be
blotted out for a season, as a nation, God multiplied the number of
his witnesses among them. Most of the prophets whose writings
have come down to us, lived either a short time before, or were
cotemporary with the destruction of Jerusalem by Nebuchadnezzar;
the warning voices of Jeremiah and Ezekiel were raised at this
juncture, to save if possible their guilty nation—with the women as
well as the men they expostulated, and admonished them of
impending judgments, but the people scornfully replied to Jeremiah
—"As for the word that thou hast spoken unto us in the name of the
Lord, we will not hearken unto thee, but we will certainly do
whatsoever thing goeth forth out of our mouth." "Therefore, thus
saith the Lord—ye have not hearkened unto me in proclaiming
liberty every one to his brother, and every one to his neighbor—
behold I proclaim a liberty for you saith the Lord, to the sword, to
the pestilence and to the famine." Are we not virtually as a nation
adopting the same impious language, and are we not exposed to the
same tremendous judgments? Shall we not in view of those things
use every laudable means to awaken our beloved country from the
slumbers of death, and baptize all our efforts with tears and with
prayers, that God may bless them. Then should our labor fail to
accomplish the end for which we pray; we shall stand acquitted at
the bar of Jehovah, and although we may share in the national
calamities which await unrepented sins, yet that blessed approval
will be ours.—"Well done good and faithful servants, enter ye into
the joy of your Lord."

We are aware that few of our colored brethren and sisters are
actively, or directly promoting the continuation of slavery; we mourn
indeed that a single instance can be adduced, of one colored person
betraying another into the fangs of those merciless wretches who go
about seeking whom they may devour; we mourn, not because the
act is more diabolical on account of the complexion, but because our
enemies seize every such instance of moral delinquency, to prove
that the people of color are lost to the feelings of humanity for each
other.

Our hearts have been filled with sorrow at the transactions which
have lately disgraced the city of New York; the forcible seizure and
consigning to cruel bondage native American citizens. In the
emporium of our commerce, in a city filled with Bibles and with
churches, we behold the revolting spectacle of rational and immortal
beings, arraigned before their fellow men, not for any crimes which
they have committed, but because they dare to call their vital breath
their own, and to take possession of that body, soul, and mind,
which their Creator gave them. We behold them manacled and
guarded by officers armed with weapons of death—guiltless of crime
and accused of none, but forced to prove that they are men and not
beasts. We marvel, as we behold these reproachful scenes, that the
God of Justice has held back his avenging sword.—"Thus saith the
Lord—execute judgment in the morning, and deliver him that is
spoiled out of the hand of the oppressor, lest my fury go out like fire
that none can quench it, because of the evil of your doings."

But although we believe that the accumulated wrongs of our


colored friends are had in remembrance before God, and that he will
assuredly visit this nation in judgment unless she repent, yet we
entreat you in the name of the Lord Jesus, to forbear any attempts
violently to rescue your brethren. Such attempts can only end in
disappointment; they infuriate public sentiment still more against
you, and furnish your blood-thirsty adversaries with a plausible
pretext, to treat you with cruelty. They bring upon all your brethren
unmerited odium, and render doubly difficult the duties of those who
have been called by Jehovah to assert the colored man's right to
freedom, and to vindicate his character from those calumnies which
have been heaped upon him. Independent, however, of all these
reasons, we beseech you to possess your souls in patience, because
present duty is unresisting submission, in accordance with the
apostolic precepts.—"Be subject not only for wrath, but for
conscience sake." "For this is thankworthy, if a man for conscience
toward God endure grief, suffering wrongfully." "For even hereunto
are we called, because Christ also suffered for us, leaving us an
example that we should follow his steps."

Let us keep in mind, that Jesus Christ was arraigned before an


earthly judge, that he endured indignity, violence and contempt.
Every innocent man who is brought before a human tribunal, and
condemned to perpetual bondage, when his judge can find no fault
in him, may be regarded as the representative of Him, who replied
to Pilate, "Thou couldst have no power against me, except it were
given thee from above: therefore he that delivered me unto thee
hath the greater sin." Suffer us to mingle our sighs, and our tears
with yours over these heart-rending scenes, these ruthless inflictions
of nameless and unutterable woes; but let us remember, that when
the Redeemer of men was taken by a band of armed ruffians, he
acted out his own sublime precept—"Resist not evil;" and when
Peter with intemperate zeal cut off the servant's ear, Jesus healed
the wound, and commanded his disciple to put up his sword again
into its place.

If we recur to the history of God's chosen people, whom he


permitted to be in bondage in the land of Egypt, we shall find that it
was not when Moses killed the Egyptian because he smote an
Israelite, that the God of the oppressed arose for their deliverance.
No, dear friends, it was when "the children of Israel sighed by
reason of the bondage, and they cried, and their cry came up unto
God by reason of the bondage. And God heard their groaning and
God remembered his covenant." Shall we distrust him now that his
covenant of mercy has been sealed with the blood of his only
begotten son—shall we resort to weapons forged by Satan, and used
by our enemies, when the Lord God omnipotent is our king, and it
behoveth his subjects to be "shod with the preparation of the gospel
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like