Dsa Using Java 简明教程
DSA using Java - Overview
What is a Data Structure?
数据结构是组织数据的一种方法,可以有效地利用数据。以下术语是数据结构的基础术语。
-
Interface − 每个数据结构都有一个接口。接口表示数据结构支持的操作集合。接口仅提供支持操作的列表、可以接受的参数类型和这些操作的返回类型。
-
Implementation − 实现提供了数据结构的内部表示形式。实现还提供了数据结构操作中使用的算法定义。
Characteristics of a Data Structure
-
Correctness − 数据结构实现应正确地实现其接口。
-
Time Complexity − 数据结构操作的运行时间或执行时间必须尽可能小。
-
Space Complexity − 数据结构操作的内存使用量应尽可能小。
Need for Data Structure
随着应用程序变得复杂且数据丰富,如今应用程序面临三个常见问题。
-
Data Search − 考虑一家商店有 100 万 (106) 件库存。如果应用程序要搜索一个项目。它必须在 100 万 (106) 个项目中每次搜索一个项目,从而降低搜索速度。随着数据增长,搜索将变得更加缓慢。
-
Processor speed − 处理器速度虽然很高,但如果数据增长到几十亿条记录,就会受到限制。
-
Multiple requests − 由于数千名用户可以在 Web 服务器上同时搜索数据,因此即使非常快的服务器在搜索数据时也会遇到故障。
为了解决上述问题,数据结构派上了用场。可以将数据组织到数据结构中,使得可能无需搜索所有项目,并且可以几乎立即搜索所需数据。
Execution Time Cases
有三个案例通常用于以相对的方式比较各种数据结构的执行时间。
-
Worst Case − 这是特定数据结构操作花费最多时间的情况。如果一个操作的最坏情况时间是 ƒ(n),那么这个操作不会花费超过 ƒ(n) 次时间,其中 ƒ(n) 表示 n 的函数。
-
Average Case − 这是描述数据结构操作的平均执行时间的情况。如果一个操作执行时间为 ƒ(n),那么 m 个操作将花费 mƒ(n) 时间。
-
Best Case − 这是描述数据结构操作最可能的执行时间的情况。如果一个操作执行时间为 ƒ(n),那么实际操作可能需要的时间是一个随机数,该随机数最多为 ƒ(n)。
DSA using Java - Environment Setup
Local Environment Setup
如果您仍希望为Java编程语言设置环境,那么本部分将指导您如何在机器上下载和设置Java。请按照以下步骤设置环境。
Java SE 可以从链接 Download Java 中免费获取。因此,您可以根据自己的操作系统下载版本。
按照说明下载 Java 并运行 .exe 以在你的计算机上安装 Java。一旦在计算机上安装了 Java,就需要设置环境变量以指向正确的安装目录:
Setting up the path for windows 2000/XP
假设你已将 Java 安装在 c:\Program Files\java\jdk 目录中:
-
右键单击“我的电脑”,然后选择“属性”。
-
单击“高级”选项卡下的“环境变量”按钮。
-
现在更改“路径”变量,使其还包含 Java 可执行文件的路径。例如,如果路径当前设置为“C:\WINDOWS\SYSTEM32”,则将路径更改为“C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin”。
Setting up the path for windows 95/98/ME
假设你已将 Java 安装在 c:\Program Files\java\jdk 目录中 −
-
编辑 'C:\autoexec.bat' 文件并在末尾添加以下行:'SET PATH=%PATH%;C:\Program Files\java\jdk\bin'
Setting up the path for Linux, UNIX, Solaris, FreeBSD:
环境变量 PATH 应设置为指向已安装 Java 二进制文件的位置。如果您在执行此操作时遇到问题,请参阅您的 shell 文档。
例如,如果您用 bash 作为您的 shell,则您将向您 '.bashrc: export PATH=/path/to/java:$PATH' 的末尾添加以下行
Popular Java Editors
要编写 Java 程序,您需要一个文本编辑器。市场上还有一些更复杂的 IDE,但目前,您可以考虑以下选项之一:
-
Notepad − 在Windows计算机上可以使用任何简单的文本编辑器,如记事本(建议用于本教程)、TextPad。
-
*Netbeans −*是一个Java IDE,它开源且免费,可以从 https://www.netbeans.org/index.html 下载。
-
Eclipse − 也是由eclipse开源社区开发的一个Java IDE,可以从 https://www.eclipse.org/ 下载。
DSA using Java - Algorithms
Algorithm concept
算法是一个按步骤执行的过程,其中定义了一组要以特定顺序执行的指令以获取所需的输出。在数据结构方面,以下是对算法的分类。
-
Search − 搜索数据结构中某个项的算法。
-
Sort − 按特定顺序对项进行排序的算法
-
Insert − 将项插入数据结构中的算法
-
Update − 更新数据结构中现有项的算法
-
Delete − 从数据结构中删除现有项的算法
Algorithm analysis
算法分析涉及到数据结构执行时间或各种操作的运行时间。操作的运行时间可定义为:每个操作执行的计算机指令数。由于任何操作的确切运行时间因计算机不同而异,我们通常会分析任何操作的运行时间作为 n 的某个函数,其中 n 为该操作在数据结构中处理的项数。
Asymptotic analysis
渐近分析是指以计算单位计算任何操作的运行时间。例如,某个操作的运行时间计算为 f(n),而另一个操作的运行时间计算为 g(n2)。这意味着第一个操作的运行时间将随着 n 的增加而线性增加,而第二个操作的运行时间将在 n 增加时呈指数级增加。同样,如果 n 非常小,则两个操作的运行时间将几乎相同。
DSA using Java - Data Structures
数据结构是用一种有效的方式组织数据的方法。以下术语是数据结构的基本术语。
Data Definition
数据定义用以下特征定义特定数据。
-
原子性 − 定义应该定义单个概念
-
可追踪性 − 定义应该是能够映射到某些数据元素的。
-
准确性 − 定义应该是明确的。
-
清晰简洁性 − 定义应该是可以理解的。
DSA using Java - Arrays
Array Basics
数组是一个容器,可以容纳固定数量的项,并且这些项应为同类型。大多数数据结构使用数组来实现其算法。以下是理解数组概念的重要术语
-
Element - 存储在数组中的每个项称为一个元素。
-
Index − 数组中每个元素的位置都有一个数字索引,该索引用于标识该元素。
Array Representation
根据以上所示的说明,以下是要考虑的重要要点。
-
Index starts with 0.
-
数组长度为 8,这意味着它可以存储 8 个元素。
-
可以通过它们的索引访问每个元素。例如,我们可以获取索引为 6 的元素 9。
Basic Operations
数组支持的基本操作如下。
-
Insertion − 在给定索引处添加一个元素。
-
Deletion − 在给定索引处删除一个元素。
-
Search − 使用给定索引或按值搜索一个元素。
-
Update − 在给定索引处更新一个元素。
在 java 中,当使用大小初始化一个数组时,它会按以下顺序为其元素分配默认值。
Data Type |
Default Value |
byte |
0 |
short |
0 |
int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d |
char |
'\u0000' |
boolean |
false |
Object |
null |
Demo
package com.tutorialspoint.array;
public class ArrayDemo {
public static void main(String[] args){
// Declare an array
int intArray[];
// Initialize an array of 8 int
// set aside memory of 8 int
intArray = new int[8];
System.out.println("Array before adding data.");
// Display elements of an array.
display(intArray);
// Operation : Insertion
// Add elements in the array
for(int i = 0; i< intArray.length; i++)
{
// place value of i at index i.
System.out.println("Adding "+i+" at index "+i);
intArray[i] = i;
}
System.out.println();
System.out.println("Array after adding data.");
display(intArray);
// Operation : Insertion
// Element at any location can be updated directly
int index = 5;
intArray[index] = 10;
System.out.println("Array after updating element at index " + index);
display(intArray);
// Operation : Search using index
// Search an element using index.
System.out.println("Data at index " + index + ": "+ intArray[index]);
// Operation : Search using value
// Search an element using value.
int value = 4;
for(int i = 0; i< intArray.length; i++)
{
if(intArray[i] == value ){
System.out.println(value + " Found at index "+i);
break;
}
}
System.out.println("Data at index " + index + ": "+ intArray[index]);
}
private static void display(int[] intArray){
System.out.print("Array : [");
for(int i = 0; i< intArray.length; i++)
{
// display value of element at index i.
System.out.print(" "+intArray[i]);
}
System.out.println(" ]");
System.out.println();
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Array before adding data.
Array : [ 0 0 0 0 0 0 0 0 ]
Adding 0 at index 0
Adding 1 at index 1
Adding 2 at index 2
Adding 3 at index 3
Adding 4 at index 4
Adding 5 at index 5
Adding 6 at index 6
Adding 7 at index 7
Array after adding data.
Array : [ 0 1 2 3 4 5 6 7 ]
Array after updating element at index 5
Array : [ 0 1 2 3 4 10 6 7 ]
Data at index 5: 10
4 Found at index: 4
DSA using Java - Linked List
Linked List Basics
链表是由包含项的链接序列。每个链接都包含到另一个链接的连接。链表是在数组之后使用第二多的数据结构。以下是理解链表概念的重要术语。
-
Link − 链表的每个链接可以存储一个称为元素的数据。
-
Next − 链表的每个链接都包含到下一个链接的链接,称为 Next。
-
LinkedList − 一个 LinkedList 包含连接到称为 First 的第一个 Link 的连接链接。
Linked List Representation
根据以上所示的说明,以下是要考虑的重要要点。
-
双向链表包含第一个链接元素。
-
每个链接都包含一个数据字段(多个字段)和一个称为 Next 的链接字段。
-
每个链接使用其 Next 链接与其下一个链接链接。
-
最后一个链接包含一个空链接来标记链表的结尾。
Types of Linked List
以下是双向链表的各种类型。
-
Simple Linked List - 项目导航仅向前。
-
Doubly Linked List - 项目可以向前和向后导航。
-
Circular Linked List - 最后一个项目包含第一个元素的链接,而第一个元素包含指向最后一个元素的链接。
Basic Operations
以下是列表支持的基本操作。
-
Insertion − 在链表的开头添加元素。
-
Deletion − 删除链表开头的元素。
-
Display - 显示完整的列表。
-
Search - 使用给定的键搜索元素。
-
Delete - 使用给定的键删除元素。
Insertion Operation
插入是一个三步过程:
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
//point it to old first node
link.next = first;
//point first to new first node
first = link;
}
Deletion Operation
删除是一个两步过程:
//delete first item
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
//mark next to first link as first
first = first.next;
//return the deleted link
return tempLink;
}
Navigation Operation
导航是一个递归步骤过程,是许多操作(如搜索、删除等)的基础:
Note
//display the list
public void display(){
//start from the beginning
Link current = first;
//navigate till the end of the list
System.out.print("[ ");
while(current != null){
//print data
current.display();
//move to next item
current = current.next;
System.out.print(" ");
}
System.out.print(" ]");
}
Sort Operation
我们使用冒泡排序对列表进行排序。
public void sort(){
int i, j, k, tempKey, tempData ;
Link current,next;
int size = length();
k = size ;
for ( i = 0 ; i < size - 1 ; i++, k-- ) {
current = first ;
next = first.next ;
for ( j = 1 ; j < k ; j++ ) {
if ( current.data > next.data ) {
tempData = current.data ;
current.data = next.data;
next.data = tempData ;
tempKey = current.key;
current.key = next.key;
next.key = tempKey;
}
current = current.next;
next = next.next;
}
}
}
Reverse Operation
以下代码演示如何逆转一个单链表。
public LinkedList reverse() {
LinkedList reversedlist = new LinkedList();
Link nextLink = null;
reversedlist.insertFirst(first.key, first.data);
Link currentLink = first;
// Until no more data in list,
// insert current link before first and move ahead.
while(currentLink.next != null){
nextLink = currentLink.next;
// Insert at start of new list.
reversedlist.insertFirst(nextLink.key, nextLink.data);
//advance to next node
currentLink = currentLink.next;
}
return reversedlist;
}
Concatenate Operation
以下代码演示如何逆转一个单链表。
public void concatenate(LinkedList list){
if(first == null){
first = list.first;
}
if(list.first == null){
return;
}
Link temp = first;
while(temp.next !=null) {
temp = temp.next;
}
temp.next = list.first;
}
Demo
package com.tutorialspoint.list;
public class Link {
public int key;
public int data;
public Link next;
public Link(int key, int data){
this.key = key;
this.data = data;
}
public void display(){
System.out.print("{"+key+","+data+"}");
}
}
package com.tutorialspoint.list;
public class LinkedList {
//this link always point to first Link
//in the Linked List
private Link first;
// create an empty linked list
public LinkedList(){
first = null;
}
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
//point it to old first node
link.next = first;
//point first to new first node
first = link;
}
//delete first item
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
//mark next to first link as first
first = first.next;
//return the deleted link
return tempLink;
}
//display the list
public void display(){
//start from the beginning
Link current = first;
//navigate till the end of the list
System.out.print("[ ");
while(current != null){
//print data
current.display();
//move to next item
current = current.next;
System.out.print(" ");
}
System.out.print(" ]");
}
//find a link with given key
public Link find(int key){
//start from the first link
Link current = first;
//if list is empty
if(first == null){
return null;
}
//navigate through list
while(current.key != key){
//if it is last node
if(current.next == null){
return null;
}else{
//go to next link
current = current.next;
}
}
//if data found, return the current Link
return current;
}
//delete a link with given key
public Link delete(int key){
//start from the first link
Link current = first;
Link previous = null;
//if list is empty
if(first == null){
return null;
}
//navigate through list
while(current.key != key){
//if it is last node
if(current.next == null){
return null;
}else{
//store reference to current link
previous = current;
//move to next link
current = current.next;
}
}
//found a match, update the link
if(current == first) {
//change first to point to next link
first = first.next;
}else {
//bypass the current link
previous.next = current.next;
}
return current;
}
//is list empty
public boolean isEmpty(){
return first == null;
}
public int length(){
int length = 0;
for(Link current = first; current!=null;
current = current.next){
length++;
}
return length;
}
public void sort(){
int i, j, k, tempKey, tempData ;
Link current,next;
int size = length();
k = size ;
for ( i = 0 ; i < size - 1 ; i++, k-- ) {
current = first ;
next = first.next ;
for ( j = 1 ; j < k ; j++ ) {
if ( current.data > next.data ) {
tempData = current.data ;
current.data = next.data;
next.data = tempData ;
tempKey = current.key;
current.key = next.key;
next.key = tempKey;
}
current = current.next;
next = next.next;
}
}
}
public LinkedList reverse() {
LinkedList reversedlist = new LinkedList();
Link nextLink = null;
reversedlist.insertFirst(first.key, first.data);
Link currentLink = first;
// Until no more data in list,
// insert current link before first and move ahead.
while(currentLink.next != null){
nextLink = currentLink.next;
// Insert at start of new list.
reversedlist.insertFirst(nextLink.key, nextLink.data);
//advance to next node
currentLink = currentLink.next;
}
return reversedlist;
}
public void concatenate(LinkedList list){
if(first == null){
first = list.first;
}
if(list.first == null){
return;
}
Link temp = first;
while(temp.next !=null) {
temp = temp.next;
}
temp.next = list.first;
}
}
package com.tutorialspoint.list;
public class LinkedListDemo {
public static void main(String args[]){
LinkedList list = new LinkedList();
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertFirst(4, 1);
list.insertFirst(5, 40);
list.insertFirst(6, 56);
System.out.print("\nOriginal List: ");
list.display();
System.out.println("");
while(!list.isEmpty()){
Link temp = list.deleteFirst();
System.out.print("Deleted value:");
temp.display();
System.out.println("");
}
System.out.print("List after deleting all items: ");
list.display();
System.out.println("");
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertFirst(4, 1);
list.insertFirst(5, 40);
list.insertFirst(6, 56);
System.out.print("Restored List: ");
list.display();
System.out.println("");
Link foundLink = list.find(4);
if(foundLink != null){
System.out.print("Element found: ");
foundLink.display();
System.out.println("");
}else{
System.out.println("Element not found.");
}
list.delete(4);
System.out.print("List after deleting an item: ");
list.display();
System.out.println("");
foundLink = list.find(4);
if(foundLink != null){
System.out.print("Element found: ");
foundLink.display();
System.out.println("");
}else{
System.out.print("Element not found. {4,1}");
}
System.out.println("");
list.sort();
System.out.print("List after sorting the data: ");
list.display();
System.out.println("");
System.out.print("Reverse of the list: ");
LinkedList list1 = list.reverse();
list1.display();
System.out.println("");
LinkedList list2 = new LinkedList();
list2.insertFirst(9, 50);
list2.insertFirst(8, 40);
list2.insertFirst(7, 20);
list.concatenate(list2);
System.out.print("List after concatenation: ");
list.display();
System.out.println("");
}
}
如果我们编译并运行上面的程序,它将产生以下结果:
Original List: [ {6,56} {5,40} {4,1} {3,30} {2,20} {1,10} ]
Deleted value:{6,56}
Deleted value:{5,40}
Deleted value:{4,1}
Deleted value:{3,30}
Deleted value:{2,20}
Deleted value:{1,10}
List after deleting all items: [ ]
Restored List: [ {6,56} {5,40} {4,1} {3,30} {2,20} {1,10} ]
Element found: {4,1}
List after deleting an item: [ {6,56} {5,40} {3,30} {2,20} {1,10} ]
Element not found. {4,1}
List after sorting the data: [ {1,10} {2,20} {3,30} {5,40} {6,56} ]
Reverse of the list: [ {6,56} {5,40} {3,30} {2,20} {1,10} ]
List after concatenation: [ {1,10} {2,20} {3,30} {5,40} {6,56} {7,20} {8,40} {9,50} ]
DSA using Java - Doubly Linked List
Doubly Linked List Basics
双向链表是链表的一种变体,与单向链表相比,它可以在两个方向(向前或向后)轻松地导航。以下是理解双向链表概念的重要术语
-
Link − 链表的每个链接可以存储一个称为元素的数据。
-
Next − 链表的每个链接都包含到下一个链接的链接,称为 Next。
-
Prev − 链表的每个链接都包含到前一个链接的链接,称为 Prev。
-
LinkedList − 一个 LinkedList 包含指向第一个称为 First 的链接的链接链接和指向最后一个链接(称为 Last)的链接链接。
Doubly Linked List Representation
根据以上所示的说明,以下是要考虑的重要要点。
-
双重 LinkedList 包含一个称为 First 和 Last 的链元素。
-
每个链接都包含一个数据字段(多个字段)和一个称为 Next 的链接字段。
-
每个链接使用其 Next 链接与其下一个链接链接。
-
每个链接使用其 Prev 链接与其上一个链接链接。
-
最后一个链接包含一个空链接来标记链表的结尾。
Basic Operations
以下是由链表支持的基本操作。
-
Insertion − 在链表的开头添加元素。
-
Deletion − 删除链表开头的元素。
-
Insert Last − 在链表的末尾添加元素。
-
Delete Last − 从链表的末尾删除元素。
-
Insert After − 在链表项后添加元素。
-
Delete − 使用键从链表删除元素。
-
Display forward − 以正向方式显示完整链表。
.
-
Display backward − 以反向方式显示完整链表。
Insertion Operation
以下代码演示在双向链表的开头执行插入操作。
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
if(isEmpty()){
//make it the last link
last = link;
}else {
//update first prev link
first.prev = link;
}
//point it to old first link
link.next = first;
//point first to new first link
first = link;
}
Deletion Operation
以下代码演示在双向链表的开头执行删除操作。
//delete link at the first location
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
//if only one link
if(first.next == null){
last = null;
}else {
first.next.prev = null;
}
first = first.next;
//return the deleted link
return tempLink;
}
Insertion at End Operation
以下代码演示在双向链表的末尾执行插入操作。
//insert link at the last location
public void insertLast(int key, int data){
//create a link
Link link = new Link(key,data);
if(isEmpty()){
//make it the last link
last = link;
}else {
//make link a new last link
last.next = link;
//mark old last node as prev of new link
link.prev = last;
}
//point last to new last node
last = link;
}
Demo
Link.java
package com.tutorialspoint.list;
public class Link {
public int key;
public int data;
public Link next;
public Link prev;
public Link(int key, int data){
this.key = key;
this.data = data;
}
public void display(){
System.out.print("{"+key+","+data+"}");
}
}
DoublyLinkedList.java
package com.tutorialspoint.list;
public class DoublyLinkedList {
//this link always point to first Link
private Link first;
//this link always point to last Link
private Link last;
// create an empty linked list
public DoublyLinkedList(){
first = null;
last = null;
}
//is list empty
public boolean isEmpty(){
return first == null;
}
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
if(isEmpty()){
//make it the last link
last = link;
}else {
//update first prev link
first.prev = link;
}
//point it to old first link
link.next = first;
//point first to new first link
first = link;
}
//insert link at the last location
public void insertLast(int key, int data){
//create a link
Link link = new Link(key,data);
if(isEmpty()){
//make it the last link
last = link;
}else {
//make link a new last link
last.next = link;
//mark old last node as prev of new link
link.prev = last;
}
//point last to new last node
last = link;
}
//delete link at the first location
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
//if only one link
if(first.next == null){
last = null;
}else {
first.next.prev = null;
}
first = first.next;
//return the deleted link
return tempLink;
}
//delete link at the last location
public Link deleteLast(){
//save reference to last link
Link tempLink = last;
//if only one link
if(first.next == null){
first = null;
}else {
last.prev.next = null;
}
last = last.prev;
//return the deleted link
return tempLink;
}
//display the list in from first to last
public void displayForward(){
//start from the beginning
Link current = first;
//navigate till the end of the list
System.out.print("[ ");
while(current != null){
//print data
current.display();
//move to next item
current = current.next;
System.out.print(" ");
}
System.out.print(" ]");
}
//display the list from last to first
public void displayBackward(){
//start from the last
Link current = last;
//navigate till the start of the list
System.out.print("[ ");
while(current != null){
//print data
current.display();
//move to next item
current = current.prev;
System.out.print(" ");
}
System.out.print(" ]");
}
//delete a link with given key
public Link delete(int key){
//start from the first link
Link current = first;
//if list is empty
if(first == null){
return null;
}
//navigate through list
while(current.key != key){
//if it is last node
if(current.next == null){
return null;
}else{
//move to next link
current = current.next;
}
}
//found a match, update the link
if(current == first) {
//change first to point to next link
first = current.next;
}else {
//bypass the current link
current.prev.next = current.next;
}
if(current == last){
//change last to point to prev link
last = current.prev;
}else {
current.next.prev = current.prev;
}
return current;
}
public boolean insertAfter(int key, int newKey, int data){
//start from the first link
Link current = first;
//if list is empty
if(first == null){
return false;
}
//navigate through list
while(current.key != key){
//if it is last node
if(current.next == null){
return false;
}else{
//move to next link
current = current.next;
}
}
Link newLink = new Link(newKey,data);
if(current==last) {
newLink.next = null;
last = newLink;
}
else {
newLink.next = current.next;
current.next.prev = newLink;
}
newLink.prev = current;
current.next = newLink;
return true;
}
}
DoublyLinkedListDemo.java
package com.tutorialspoint.list;
public class DoublyLinkedListDemo {
public static void main(String args[]){
DoublyLinkedList list = new DoublyLinkedList();
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertLast(4, 1);
list.insertLast(5, 40);
list.insertLast(6, 56);
System.out.print("\nList (First to Last): ");
list.displayForward();
System.out.println("");
System.out.print("\nList (Last to first): ");
list.displayBackward();
System.out.print("\nList , after deleting first record: ");
list.deleteFirst();
list.displayForward();
System.out.print("\nList , after deleting last record: ");
list.deleteLast();
list.displayForward();
System.out.print("\nList , insert after key(4) : ");
list.insertAfter(4,7, 13);
list.displayForward();
System.out.print("\nList , after delete key(4) : ");
list.delete(4);
list.displayForward();
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
List (First to Last): [ {3,30} {2,20} {1,10} {4,1} {5,40} {6,56} ]
List (Last to first): [ {6,56} {5,40} {4,1} {1,10} {2,20} {3,30} ]
List (First to Last) after deleting first record: [ {2,20} {1,10} {4,1} {5,40} {6,56} ]
List (First to Last) after deleting last record: [ {2,20} {1,10} {4,1} {5,40} ]
List (First to Last) insert after key(4) : [ {2,20} {1,10} {4,1} {7,13} {5,40} ]
List (First to Last) after delete key(4) : [ {2,20} {1,10} {7,13} {5,40} ]
DSA using Java - Circular Linked List
Doubly Linked List as Circular
根据上面显示的说明,以下是需要考虑的重要事项。
-
在单链表和双链表两种情况下,最后一个链接的“next”都指向第一个链接。
-
在双链表中,第一个链接的“prev”指向最后一个链接。
length Operation
以下代码演示基于单链表的循环链表中的插入操作。
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
if (isEmpty()) {
first = link;
first.next = first;
}
else{
//point it to old first node
link.next = first;
//point first to new first node
first = link;
}
}
Deletion Operation
以下代码演示基于单链表的循环链表中的删除操作。
//delete link at the first location
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
//if only one link
if(first.next == null){
last = null;
}else {
first.next.prev = null;
}
first = first.next;
//return the deleted link
return tempLink;
}
Display List Operation
以下代码演示循环链表中的显示列表操作。
public void display(){
//start from the beginning
Link current = first;
//navigate till the end of the list
System.out.print("[ ");
if(first != null){
while(current.next != current){
//print data
current.display();
//move to next item
current = current.next;
System.out.print(" ");
}
}
System.out.print(" ]");
}
Demo
Link.java
package com.tutorialspoint.list;
public class CircularLinkedList {
//this link always point to first Link
private Link first;
// create an empty linked list
public CircularLinkedList(){
first = null;
}
public boolean isEmpty(){
return first == null;
}
public int length(){
int length = 0;
//if list is empty
if(first == null){
return 0;
}
Link current = first.next;
while(current != first){
length++;
current = current.next;
}
return length;
}
//insert link at the first location
public void insertFirst(int key, int data){
//create a link
Link link = new Link(key,data);
if (isEmpty()) {
first = link;
first.next = first;
}
else{
//point it to old first node
link.next = first;
//point first to new first node
first = link;
}
}
//delete first item
public Link deleteFirst(){
//save reference to first link
Link tempLink = first;
if(first.next == first){
first = null;
return tempLink;
}
//mark next to first link as first
first = first.next;
//return the deleted link
return tempLink;
}
public void display(){
//start from the beginning
Link current = first;
//navigate till the end of the list
System.out.print("[ ");
if(first != null){
while(current.next != current){
//print data
current.display();
//move to next item
current = current.next;
System.out.print(" ");
}
}
System.out.print(" ]");
}
}
DoublyLinkedListDemo.java
package com.tutorialspoint.list;
public class CircularLinkedListDemo {
public static void main(String args[]){
CircularLinkedList list = new CircularLinkedList();
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertFirst(4, 1);
list.insertFirst(5, 40);
list.insertFirst(6, 56);
System.out.print("\nOriginal List: ");
list.display();
System.out.println("");
while(!list.isEmpty()){
Link temp = list.deleteFirst();
System.out.print("Deleted value:");
temp.display();
System.out.println("");
}
System.out.print("List after deleting all items: ");
list.display();
System.out.println("");
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Original List: [ {6,56} {5,40} {4,1} {3,30} {2,20} ]
Deleted value:{6,56}
Deleted value:{5,40}
Deleted value:{4,1}
Deleted value:{3,30}
Deleted value:{2,20}
Deleted value:{1,10}
List after deleting all items: [ ]
DSA using Java - Stack
Overview
堆栈是一种数据结构,它仅允许在某一端对数据执行操作。它只允许访问最后插入的数据。堆栈也被称为 LIFO(后进先出)数据结构,入栈和出栈操作以这样的方式相关联,即只有最后入栈(添加到堆栈)的项目可以出栈(从堆栈中移除)。
Basic Operations
堆栈的以下两个主要操作如下所示。
-
Push − 将一个元素压入堆栈的顶部。
-
Pop − 从堆栈的顶部弹出一个元素。
堆栈支持的更多操作如下所示。
-
Peek − 获取堆栈的顶部元素。
-
isFull − 检查堆栈是否已满。
-
isEmpty − 检查堆栈是否为空。
Push Operation
每当一个元素压入堆栈时,堆栈将该元素存储在存储区的顶部并增加顶部索引以备将来使用。如果存储区已满,则通常会显示一条错误消息。
// push item on the top of the stack
public void push(int data) {
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
Pop Operation
每当一个元素要从堆栈弹出时,堆栈都会从存储区的顶部检索该元素并减少顶部索引以供以后使用。
// pop item from the top of the stack
public int pop() {
// retrieve data and decrement the top by 1
return intArray[top--];
}
Stack Implementation
Stack.java
package com.tutorialspoint.datastructure;
public class Stack {
private int size; // size of the stack
private int[] intArray; // stack storage
private int top; // top of the stack
// Constructor
public Stack(int size){
this.size = size;
intArray = new int[size]; //initialize array
top = -1; //stack is initially empty
}
// Operation : Push
// push item on the top of the stack
public void push(int data) {
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
// Operation : Pop
// pop item from the top of the stack
public int pop() {
//retrieve data and decrement the top by 1
return intArray[top--];
}
// Operation : Peek
// view the data at top of the stack
public int peek() {
//retrieve data from the top
return intArray[top];
}
// Operation : isFull
// return true if stack is full
public boolean isFull(){
return (top == size-1);
}
// Operation : isEmpty
// return true if stack is empty
public boolean isEmpty(){
return (top == -1);
}
}
Demo Program
StackDemo.java
package com.tutorialspoint.datastructure;
public class StackDemo {
public static void main (String[] args){
// make a new stack
Stack stack = new Stack(10);
// push items on to the stack
stack.push(3);
stack.push(5);
stack.push(9);
stack.push(1);
stack.push(12);
stack.push(15);
System.out.println("Element at top of the stack: " + stack.peek());
System.out.println("Elements: ");
// print stack data
while(!stack.isEmpty()){
int data = stack.pop();
System.out.println(data);
}
System.out.println("Stack full: " + stack.isFull());
System.out.println("Stack empty: " + stack.isEmpty());
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Element at top of the stack: 15
Elements:
15
12
1
9
5
3
Stack full: false
Stack empty: true
DSA using Java - Parsing Expressions
像 2*(3*4) 这样的普通算术表达式对于人类来说更容易解析,但对于算法来说,解析这种表达式はかなり困难。为了解决这个困难,算法可以使用两步法来解析算术表达式。
-
将提供的算术表达式转换为后缀表示。
-
Evaluate the postfix notation.
.
Postfix Notation
后缀表示法不同于普通算术表达式或中缀表示法,其中运算符位于操作数后面。例如,考虑以下示例:
Sr.No |
Infix Notation |
Postfix Notation |
1 |
A+B |
AB+ |
2 |
(A+B)*C |
AB+C* |
3 |
A*(B+C) |
ABC+* |
4 |
A/B+C/D |
AB/CD/+ |
5 |
(A+B)*(C+D) |
AB+CD+* |
6 |
((A+B)*C)-D |
AB+C*D- |
Infix to PostFix Conversion
在研究将中缀转换为后缀表示法的方法之前,我们需要考虑中缀表达式求值的基本原理。
-
中缀表达式的求值从左到右开始。
-
记住优先级,例如 * 的优先级高于 +。 例如
2+3*4 = 2+12.2+3*4 = 14。
-
使用括号覆盖优先权,例如
(2+3)*4 = 5*4。(2+3)*4= 20。
现在让我们手动将一个简单の中缀表达式 A+B*C 转换成一个后缀表达式。
Step |
Character read |
到目前为止解析的中缀表达式 |
到目前为止开发了后缀表达式 |
Remarks |
1 |
A |
A |
A |
|
2 |
+ |
A+ |
A |
|
3 |
B |
A+B |
AB |
|
4 |
* |
A+B* |
AB |
+ 无法复制,因为 * 的优先级更高。 |
5 |
C |
A+B*C |
ABC |
|
6 |
A+B*C |
ABC* |
复制 * 因为有两个操作数 B 和 C |
|
7 |
A+B*C |
ABC*+ |
复制 + 因为有两个操作数 BC 和 A |
现在,让我们使用栈将上述中缀表达式 A+B*C 转换为后缀表达式。
Step |
Character read |
到目前为止解析的中缀表达式 |
到目前为止开发了后缀表达式 |
Stack Contents |
Remarks |
1 |
A |
A |
A |
||
2 |
+ |
A+ |
A |
+ |
将 + 运算符压入栈中。 |
3 |
B |
A+B |
AB |
+ |
|
4 |
* |
A+B* |
AB |
+* |
运算符 * 的优先级高于 。将 * 运算符压入栈中。否则, 会弹出。 |
5 |
C |
A+B*C |
ABC |
+* |
|
6 |
A+B*C |
ABC* |
+ |
没有更多的操作数,弹出 * 运算符。 |
|
7 |
A+B*C |
ABC*+ |
Pop the + operator. |
现在让我们看另一个示例,通过使用栈将中缀表达式 A*(B+C) 转换为后缀表达式。
Step |
Character read |
到目前为止解析的中缀表达式 |
到目前为止开发了后缀表达式 |
Stack Contents |
Remarks |
1 |
A |
A |
A |
||
2 |
* |
A* |
A |
* |
将 * 运算符压入栈中。 |
3 |
( |
A*( |
A |
*( |
将 ( 压入栈中。 |
4 |
B |
A*(B |
AB |
*( |
|
5 |
+ |
A*(B+ |
AB |
*(+ |
将 + 压入栈中。 |
6 |
C |
A*(B+C |
ABC |
*(+ |
|
7 |
) |
A*(B+C) |
ABC+ |
*( |
Pop the + operator. |
8 |
A*(B+C) |
ABC+ |
* |
Pop the ( operator. |
|
9 |
A*(B+C) |
ABC+* |
弹出其余运算符。 |
Demo program
现在,我们将展示使用栈将中缀表达式转换为后缀表达式,然后计算后缀表达式。
package com.tutorialspoint.expression;
public class Stack {
private int size;
private int[] intArray;
private int top;
//Constructor
public Stack(int size){
this.size = size;
intArray = new int[size];
top = -1;
}
//push item on the top of the stack
public void push(int data) {
if(!isFull()){
//increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
//pop item from the top of the stack
public int pop() {
//retrieve data and decrement the top by 1
return intArray[top--];
}
//view the data at top of the stack
public int peek() {
//retrieve data from the top
return intArray[top];
}
//return true if stack is full
public boolean isFull(){
return (top == size-1);
}
//return true if stack is empty
public boolean isEmpty(){
return (top == -1);
}
}
InfixToPostFix.java
package com.tutorialspoint.expression;
public class InfixToPostfix {
private Stack stack;
private String input = "";
private String output = "";
public InfixToPostfix(String input){
this.input = input;
stack = new Stack(input.length());
}
public String translate(){
for(int i=0;i<input.length();i++){
char ch = input.charAt(i);
switch(ch){
case '+':
case '-':
gotOperator(ch, 1);
break;
case '*':
case '/':
gotOperator(ch, 2);
break;
case '(':
stack.push(ch);
break;
case ')':
gotParenthesis(ch);
break;
default:
output = output+ch;
break;
}
}
while(!stack.isEmpty()){
output = output + (char)stack.pop();
}
return output;
}
//got operator from input
public void gotOperator(char operator, int precedence){
while(!stack.isEmpty()){
char prevOperator = (char)stack.pop();
if(prevOperator == '('){
stack.push(prevOperator);
break;
}else{
int precedence1;
if(prevOperator == '+' || prevOperator == '-'){
precedence1 = 1;
}else{
precedence1 = 2;
}
if(precedence1 < precedence){
stack.push(Character.getNumericValue(prevOperator));
break;
}else{
output = output + prevOperator;
}
}
}
stack.push(operator);
}
//got operator from input
public void gotParenthesis(char parenthesis){
while(!stack.isEmpty()){
char ch = (char)stack.pop();
if(ch == '('){
break;
}else{
output = output + ch;
}
}
}
}
PostFixParser.java
package com.tutorialspoint.expression;
public class PostFixParser {
private Stack stack;
private String input;
public PostFixParser(String postfixExpression){
input = postfixExpression;
stack = new Stack(input.length());
}
public int evaluate(){
char ch;
int firstOperand;
int secondOperand;
int tempResult;
for(int i=0;i<input.length();i++){
ch = input.charAt(i);
if(ch >= '0' && ch <= '9'){
stack.push(Character.getNumericValue(ch));
}else{
firstOperand = stack.pop();
secondOperand = stack.pop();
switch(ch){
case '+':
tempResult = firstOperand + secondOperand;
break;
case '-':
tempResult = firstOperand - secondOperand;
break;
case '*':
tempResult = firstOperand * secondOperand;
break;
case '/':
tempResult = firstOperand / secondOperand;
break;
default:
tempResult = 0;
}
stack.push(tempResult);
}
}
return stack.pop();
}
}
PostFixDemo.java
package com.tutorialspoint.expression;
public class PostFixDemo {
public static void main(String args[]){
String input = "1*(2+3)";
InfixToPostfix translator = new InfixToPostfix(input);
String output = translator.translate();
System.out.println("Infix expression is: " + input);
System.out.println("Postfix expression is: " + output);
PostFixParser parser = new PostFixParser(output);
System.out.println("Result is: " + parser.evaluate());
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Infix expression is: 1*(2+3)
Postfix expression is: 123+*
Result is: 5
DSA using Java - Queue
Basic Operations
-
insert / enqueue − 向队列后部添加项目。
-
remove / dequeue − 从队列前部删除项目。
在本文中,我们将使用数组实现队列。队列支持以下更多操作。
-
Peek − 获取队列前部的元素。
-
isFull − 检查队列是否已满。
-
isEmpty − 检查队列是否为空。
Insert / Enqueue Operation
每当将元素插入队列时,队列会增加后索引以供以后使用,并将该元素存储在存储的后端。如果后端到达最后一个索引,并且它被转到最底层。这种安排称为环绕,这种队列是循环队列。此方法也称为入队操作。
public void insert(int data){
if(!isFull()){
if(rear == MAX-1){
rear = -1;
}
intArray[++rear] = data;
itemCount++;
}
}
Remove / Dequeue Operation
每当要从队列中移除一个元素时,队列使用前索引获取该元素并增加前索引。作为环绕设置,如果前索引大于数组的最大索引,则将其设置为 0。
public int remove(){
int data = intArray[front++];
if(front == MAX){
front = 0;
}
itemCount--;
return data;
}
Queue Implementation
Queue.java
package com.tutorialspoint.datastructure;
public class Queue {
private final int MAX;
private int[] intArray;
private int front;
private int rear;
private int itemCount;
public Queue(int size){
MAX = size;
intArray = new int[MAX];
front = 0;
rear = -1;
itemCount = 0;
}
public void insert(int data){
if(!isFull()){
if(rear == MAX-1){
rear = -1;
}
intArray[++rear] = data;
itemCount++;
}
}
public int remove(){
int data = intArray[front++];
if(front == MAX){
front = 0;
}
itemCount--;
return data;
}
public int peek(){
return intArray[front];
}
public boolean isEmpty(){
return itemCount == 0;
}
public boolean isFull(){
return itemCount == MAX;
}
public int size(){
return itemCount;
}
}
Demo Program
QueueDemo.java
package com.tutorialspoint.datastructure;
public class QueueDemo {
public static void main(String[] args){
Queue queue = new Queue(6);
//insert 5 items
queue.insert(3);
queue.insert(5);
queue.insert(9);
queue.insert(1);
queue.insert(12);
// front : 0
// rear : 4
// ------------------
// index : 0 1 2 3 4
// ------------------
// queue : 3 5 9 1 12
queue.insert(15);
// front : 0
// rear : 5
// ---------------------
// index : 0 1 2 3 4 5
// ---------------------
// queue : 3 5 9 1 12 15
if(queue.isFull()){
System.out.println("Queue is full!");
}
//remove one item
int num = queue.remove();
System.out.println("Element removed: "+num);
// front : 1
// rear : 5
// -------------------
// index : 1 2 3 4 5
// -------------------
// queue : 5 9 1 12 15
//insert more items
queue.insert(16);
// front : 1
// rear : -1
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 5 9 1 12 15
//As queue is full, elements will not be inserted.
queue.insert(17);
queue.insert(18);
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 5 9 1 12 15
System.out.println("Element at front: "+queue.peek());
System.out.println("----------------------");
System.out.println("index : 5 4 3 2 1 0");
System.out.println("----------------------");
System.out.print("Queue: ");
while(!queue.isEmpty()){
int n = queue.remove();
System.out.print(n +" ");
}
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Queue is full!
Element removed: 3
Element at front: 5
----------------------
index : 5 4 3 2 1 0
----------------------
Queue: 5 9 1 12 15 16
DSA using Java - Priority Queue
Overview
优先队列是一种比队列更专业的データ结构。与普通队列一样,优先队列具有相同的方法,但有一个主要区别。在优先队列中,项目按键值排序,因此键值最小的项目在前面,键值最大的项目在后面,反之亦然。因此,我们将优先级分配给项目的键值。值越低,优先级越高。以下是优先队列的主要方法。
Priority Queue Representation
在本文中,我们将使用数组实现队列。队列支持以下更多操作。
-
Peek − 获取队列前部的元素。
-
isFull − 检查队列是否已满。
-
isEmpty − 检查队列是否为空。
Insert / Enqueue Operation
每当将元素插入队列时,优先队列会根据其顺序插入项目。在此处,我们假设具有高值的具有低优先级。
public void insert(int data){
int i =0;
if(!isFull()){
// if queue is empty, insert the data
if(itemCount == 0){
intArray[itemCount++] = data;
}else{
// start from the right end of the queue
for(i = itemCount - 1; i >= 0; i-- ){
// if data is larger, shift existing item to right end
if(data > intArray[i]){
intArray[i+1] = intArray[i];
}else{
break;
}
}
// insert the data
intArray[i+1] = data;
itemCount++;
}
}
}
Remove / Dequeue Operation
每当要从队列中移除一个元素时,队列使用项目计数获取元素。一旦移除元素。项目计数减少一。
public int remove(){
return intArray[--itemCount];
}
Priority Queue Implementation
PriorityQueue.java
package com.tutorialspoint.datastructure;
public class PriorityQueue {
private final int MAX;
private int[] intArray;
private int itemCount;
public PriorityQueue(int size){
MAX = size;
intArray = new int[MAX];
itemCount = 0;
}
public void insert(int data){
int i =0;
if(!isFull()){
// if queue is empty, insert the data
if(itemCount == 0){
intArray[itemCount++] = data;
}else{
// start from the right end of the queue
for(i = itemCount - 1; i >= 0; i-- ){
// if data is larger, shift existing item to right end
if(data > intArray[i]){
intArray[i+1] = intArray[i];
}else{
break;
}
}
// insert the data
intArray[i+1] = data;
itemCount++;
}
}
}
public int remove(){
return intArray[--itemCount];
}
public int peek(){
return intArray[itemCount - 1];
}
public boolean isEmpty(){
return itemCount == 0;
}
public boolean isFull(){
return itemCount == MAX;
}
public int size(){
return itemCount;
}
}
Demo Program
PriorityQueueDemo.java
package com.tutorialspoint.datastructure;
public class PriorityQueueDemo {
public static void main(String[] args){
PriorityQueue queue = new PriorityQueue(6);
//insert 5 items
queue.insert(3);
queue.insert(5);
queue.insert(9);
queue.insert(1);
queue.insert(12);
// ------------------
// index : 0 1 2 3 4
// ------------------
// queue : 12 9 5 3 1
queue.insert(15);
// ---------------------
// index : 0 1 2 3 4 5
// ---------------------
// queue : 15 12 9 5 3 1
if(queue.isFull()){
System.out.println("Queue is full!");
}
//remove one item
int num = queue.remove();
System.out.println("Element removed: "+num);
// ---------------------
// index : 0 1 2 3 4
// ---------------------
// queue : 15 12 9 5 3
//insert more items
queue.insert(16);
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 15 12 9 5 3
//As queue is full, elements will not be inserted.
queue.insert(17);
queue.insert(18);
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 15 12 9 5 3
System.out.println("Element at front: "+queue.peek());
System.out.println("----------------------");
System.out.println("index : 5 4 3 2 1 0");
System.out.println("----------------------");
System.out.print("Queue: ");
while(!queue.isEmpty()){
int n = queue.remove();
System.out.print(n +" ");
}
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Queue is full!
Element removed: 1
Element at front: 3
----------------------
index : 5 4 3 2 1 0
----------------------
Queue: 3 5 9 12 15 16
DSA using Java - Tree
Overview
树表示通过边连接起来的多个节点。我们将专门讨论二叉树或二叉搜索树。
二叉树是一个特殊的数据结构,用于数据存储。二叉树有一个特殊条件,即每个节点最多可以有两个子节点。二叉树同时具有有序数组和链表的优点,如搜索像在已排序数组中一样快速,插入或删除操作像在链表中一样快。
Terms
以下是关于树的一些重要术语。
-
Path − 路径是指沿着树边缘的一系列节点。
-
Root − 树顶部的节点称为根节点。每个树只有一个根节点,并且从根节点到任何节点只有一条路径。
-
Parent − 除了根节点之外的任何节点都有一条向上的边连接到一个称为父节点的节点。
-
Child − 通过向下的边与给定节点相连接的下方节点称为其子节点。
-
Leaf − 没有子节点的节点称为叶节点。
-
Subtree − 子树表示节点的后代。
-
Visiting − 访问是指在控制权在节点上的时候检查节点的值。
-
Traversing − 遍历指按照特定顺序经过节点。
-
Levels − 节点的等级表示节点的代。如果根节点在第 0 级,那么它的下一个子节点在第 1 级,它的孙子节点在第 2 级,以此类推。
-
keys − 键表示节点的值,基于此值针对节点执行搜索操作。
二叉搜索树表现出一种特殊的行为。节点的左子节点的值必须小于其父节点的值,节点的右子节点的值必须大于其父节点的值。
Basic Operations
下面是一些树的基本基本操作。
-
Search − 在树中搜索一个元素。
-
Insert − 在树中插入一个元素。
-
Preorder Traversal - 以先序方式遍历树。
-
Inorder Traversal - 以中序方式遍历树。
-
Postorder Traversal - 以后序方式遍历树。
Node
定义一个节点,它具有一些数据、针对其左侧和右侧子节点的引用。
public class Node {
public int data;
public Node leftChild;
public Node rightChild;
public Node(){}
public void display(){
System.out.print("("+data+ ")");
}
}
Search Operation
如果某一元素搜索。从根节点开始搜索,此时,如果数据小于键值,在左子树中搜索元素,否则,在右子树中搜索元素。遵循相同的算法针对每个节点。
public Node search(int data){
Node current = root;
System.out.print("Visiting elements: ");
while(current.data != data){
if(current != null)
System.out.print(current.data + " ");
//go to left tree
if(current.data > data){
current = current.leftChild;
}//else go to right tree
else{
current = current.rightChild;
}
//not found
if(current == null){
return null;
}
}
return current;
}
Insert Operation
如果某一元素要插入。首先,找到它适当的位置。从根节点开始搜索,此时,如果数据小于键值,在左子树中查找空位置,并插入数据。否则,在右子树中查找空位置,并插入数据。
public void insert(int data){
Node tempNode = new Node();
tempNode.data = data;
//if tree is empty
if(root == null){
root = tempNode;
}else{
Node current = root;
Node parent = null;
while(true){
parent = current;
//go to left of the tree
if(data < parent.data){
current = current.leftChild;
//insert to the left
if(current == null){
parent.leftChild = tempNode;
return;
}
}//go to right of the tree
else{
current = current.rightChild;
//insert to the right
if(current == null){
parent.rightChild = tempNode;
return;
}
}
}
}
}
Preorder Traversal
这是一个简单的三步流程。
-
visit root node
-
traverse left subtree
-
traverse right subtree
private void preOrder(Node root){
if(root!=null){
System.out.print(root.data + " ");
preOrder(root.leftChild);
preOrder(root.rightChild);
}
}
Inorder Traversal
这是一个简单的三步流程。
-
traverse left subtree
-
visit root node
-
traverse right subtree
private void inOrder(Node root){
if(root!=null){
inOrder(root.leftChild);
System.out.print(root.data + " ");
inOrder(root.rightChild);
}
}
Postorder Traversal
这是一个简单的三步流程。
-
traverse left subtree
-
traverse right subtree
-
visit root node
private void postOrder(Node root){
if(root!=null){
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.print(root.data + " ");
}
}
Tree Implementation
Node.java
package com.tutorialspoint.datastructure;
public class Node {
public int data;
public Node leftChild;
public Node rightChild;
public Node(){}
public void display(){
System.out.print("("+data+ ")");
}
}
Tree.java
package com.tutorialspoint.datastructure;
public class Tree {
private Node root;
public Tree(){
root = null;
}
public Node search(int data){
Node current = root;
System.out.print("Visiting elements: ");
while(current.data != data){
if(current != null)
System.out.print(current.data + " ");
//go to left tree
if(current.data > data){
current = current.leftChild;
}//else go to right tree
else{
current = current.rightChild;
}
//not found
if(current == null){
return null;
}
}
return current;
}
public void insert(int data){
Node tempNode = new Node();
tempNode.data = data;
//if tree is empty
if(root == null){
root = tempNode;
}else{
Node current = root;
Node parent = null;
while(true){
parent = current;
//go to left of the tree
if(data < parent.data){
current = current.leftChild;
//insert to the left
if(current == null){
parent.leftChild = tempNode;
return;
}
}//go to right of the tree
else{
current = current.rightChild;
//insert to the right
if(current == null){
parent.rightChild = tempNode;
return;
}
}
}
}
}
public void traverse(int traversalType){
switch(traversalType){
case 1:
System.out.print("\nPreorder traversal: ");
preOrder(root);
break;
case 2:
System.out.print("\nInorder traversal: ");
inOrder(root);
break;
case 3:
System.out.print("\nPostorder traversal: ");
postOrder(root);
break;
}
}
private void preOrder(Node root){
if(root!=null){
System.out.print(root.data + " ");
preOrder(root.leftChild);
preOrder(root.rightChild);
}
}
private void inOrder(Node root){
if(root!=null){
inOrder(root.leftChild);
System.out.print(root.data + " ");
inOrder(root.rightChild);
}
}
private void postOrder(Node root){
if(root!=null){
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.print(root.data + " ");
}
}
}
Demo Program
TreeDemo.java
package com.tutorialspoint.datastructure;
public class TreeDemo {
public static void main(String[] args){
Tree tree = new Tree();
/* 11 //Level 0
*/
tree.insert(11);
/* 11 //Level 0
* |
* |---20 //Level 1
*/
tree.insert(20);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
*/
tree.insert(3);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* |--42 //Level 2
*/
tree.insert(42);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* |--42 //Level 2
* |
* |--54 //Level 3
*/
tree.insert(54);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* 16--|--42 //Level 2
* |
* |--54 //Level 3
*/
tree.insert(16);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* 16--|--42 //Level 2
* |
* 32--|--54 //Level 3
*/
tree.insert(32);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* |
* 32--|--54 //Level 3
*/
tree.insert(9);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* | |
* 4--| 32--|--54 //Level 3
*/
tree.insert(4);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* | |
* 4--|--10 32--|--54 //Level 3
*/
tree.insert(10);
Node node = tree.search(32);
if(node!=null){
System.out.print("Element found.");
node.display();
System.out.println();
}else{
System.out.println("Element not found.");
}
Node node1 = tree.search(2);
if(node1!=null){
System.out.println("Element found.");
node1.display();
System.out.println();
}else{
System.out.println("Element not found.");
}
//pre-order traversal
//root, left ,right
tree.traverse(1);
//in-order traversal
//left, root ,right
tree.traverse(2);
//post order traversal
//left, right, root
tree.traverse(3);
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Visiting elements: 11 20 42 Element found.(32)
Visiting elements: 11 3 Element not found.
Preorder traversal: 11 3 9 4 10 20 16 42 32 54
Inorder traversal: 3 4 9 10 11 16 20 32 42 54
Postorder traversal: 4 10 9 3 16 32 54 42 20 11
DSA using Java - Hash Table
Hashing
哈希是一种将一系列键值转换为一系列数组索引的技术。我们将使用模运算符来获得一系列键值。考虑一个大小为 20 的哈希表示例,以下项目需要存储。项目采用 (key,value) 格式。
-
(1,20)
-
(2,70)
-
(42,80)
-
(4,25)
-
(12,44)
-
(14,32)
-
(17,11)
-
(13,78)
-
(37,98)
Sr.No. |
Key |
Hash |
Array Index |
1 |
1 |
1 % 20 = 1 |
1 |
2 |
2 |
2 % 20 = 2 |
2 |
3 |
42 |
42 % 20 = 2 |
2 |
4 |
4 |
4 % 20 = 4 |
4 |
5 |
12 |
12 % 20 = 12 |
12 |
6 |
14 |
14 % 20 = 14 |
14 |
7 |
17 |
17 % 20 = 17 |
17 |
8 |
13 |
13 % 20 = 13 |
13 |
9 |
37 |
37 % 20 = 17 |
17 |
Linear Probing
我们可以看到,可能发生使用哈希技术创建的索引已经是数组的已用索引。在这种情况下,我们可以通过查看下一个单元格来搜索数组中的下一个空闲位置,直到我们找到一个空闲单元格。这种技术称为线性探查。
Sr.No. |
Key |
Hash |
Array Index |
在线性探查之后,数组索引 |
1 |
1 |
1 % 20 = 1 |
1 |
1 |
2 |
2 |
2 % 20 = 2 |
2 |
2 |
3 |
42 |
42 % 20 = 2 |
2 |
3 |
4 |
4 |
4 % 20 = 4 |
4 |
4 |
5 |
12 |
12 % 20 = 12 |
12 |
12 |
6 |
14 |
14 % 20 = 14 |
14 |
14 |
7 |
17 |
17 % 20 = 17 |
17 |
17 |
8 |
13 |
13 % 20 = 13 |
13 |
13 |
9 |
37 |
37 % 20 = 17 |
17 |
18 |
DataItem
定义一个具有某些数据和键的数据项,根据该键在哈希表中进行搜索。
public class DataItem {
private int key;
private int data;
public DataItem(int key, int data){
this.key = key;
this.data = data;
}
public int getKey(){
return key;
}
public int getData(){
return data;
}
}
Search Operation
每当要搜索元素时。计算已传递键的哈希代码,并使用该哈希代码作为数组中的索引来定位该元素。如果在计算的哈希代码中没有找到元素,请使用线性探测获得元素。
public DataItem search(int key){
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] !=null){
if(hashArray[hashIndex].getKey() == key)
return hashArray[hashIndex];
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
return null;
}
Insert Operation
每当要插入元素时。计算已传递键的哈希代码,并使用该哈希代码作为数组中的索引来定位该索引。如果在计算的哈希代码中找到了某个元素,请对空位置使用线性探测。
public void insert(DataItem item){
int key = item.getKey();
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty or deleted cell
while(hashArray[hashIndex] !=null
&& hashArray[hashIndex].getKey() != -1){
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
hashArray[hashIndex] = item;
}
Delete Operation
每当要删除元素时。计算已传递键的哈希代码,并使用该哈希代码作为数组中的索引来定位该索引。如果在计算的哈希代码中找不到元素,请使用线性探测获得元素。找到后,在那里存储一个虚拟项来保持哈希表的完整性能。
public DataItem delete(DataItem item){
int key = item.getKey();
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] !=null){
if(hashArray[hashIndex].getKey() == key){
DataItem temp = hashArray[hashIndex];
//assign a dummy item at deleted position
hashArray[hashIndex] = dummyItem;
return temp;
}
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
return null;
}
HashTable Implementation
DataItem.java
package com.tutorialspoint.datastructure;
public class DataItem {
private int key;
private int data;
public DataItem(int key, int data){
this.key = key;
this.data = data;
}
public int getKey(){
return key;
}
public int getData(){
return data;
}
}
HashTable.java
package com.tutorialspoint.datastructure;
public class HashTable {
private DataItem[] hashArray;
private int size;
private DataItem dummyItem;
public HashTable(int size){
this.size = size;
hashArray = new DataItem[size];
dummyItem = new DataItem(-1,-1);
}
public void display(){
for(int i=0; i<size; i++) {
if(hashArray[i] != null)
System.out.print(" ("
+hashArray[i].getKey()+","
+hashArray[i].getData() + ") ");
else
System.out.print(" ~~ ");
}
System.out.println("");
}
public int hashCode(int key){
return key % size;
}
public DataItem search(int key){
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] !=null){
if(hashArray[hashIndex].getKey() == key)
return hashArray[hashIndex];
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
return null;
}
public void insert(DataItem item){
int key = item.getKey();
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty or deleted cell
while(hashArray[hashIndex] !=null
&& hashArray[hashIndex].getKey() != -1){
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
hashArray[hashIndex] = item;
}
public DataItem delete(DataItem item){
int key = item.getKey();
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] !=null){
if(hashArray[hashIndex].getKey() == key){
DataItem temp = hashArray[hashIndex];
//assign a dummy item at deleted position
hashArray[hashIndex] = dummyItem;
return temp;
}
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= size;
}
return null;
}
}
Demo Program
HashTableDemo.java
package com.tutorialspoint.datastructure;
public class HashTableDemo {
public static void main(String[] args){
HashTable hashTable = new HashTable(20);
hashTable.insert(new DataItem(1, 20));
hashTable.insert(new DataItem(2, 70));
hashTable.insert(new DataItem(42, 80));
hashTable.insert(new DataItem(4, 25));
hashTable.insert(new DataItem(12, 44));
hashTable.insert(new DataItem(14, 32));
hashTable.insert(new DataItem(17, 11));
hashTable.insert(new DataItem(13, 78));
hashTable.insert(new DataItem(37, 97));
hashTable.display();
DataItem item = hashTable.search(37);
if(item != null){
System.out.println("Element found: "+ item.getData());
}else{
System.out.println("Element not found");
}
hashTable.delete(item);
item = hashTable.search(37);
if(item != null){
System.out.println("Element found: "+ item.getData());
}else{
System.out.println("Element not found");
}
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
~~ (1,20) (2,70) (42,80) (4,25) ~~ ~~ ~~ ~~ ~~ ~~ ~~ (12,44) (13,78) (14,32) ~~ ~~ (17,11) (37,97) ~~
Element found: 97
Element not found
DSA using Java - Heap
Overview
堆表示一种特殊基于树的数据结构,用于表示优先级队列或堆排序。我们具体来讨论二叉堆树。
二叉堆树可以分类为具有两个约束的二叉树 −
-
Completeness − 二叉堆树是一个完全二叉树,除了最后一层可能没有所有元素,但从左到右的元素应该填充。
-
Heapness − 所有父节点都应该大于或小于它们的子节点。如果父节点大于其子节点,则称为最大堆,否则称为最小堆。最大堆用于堆排序,而最小堆用于优先级队列。我们正在考虑最小堆,并将使用数组实现相同的最小堆。
Basic Operations
以下是最小堆的基本主要操作,如下。
-
Insert − 在堆中插入一个元素。
-
Get Minimum − 从堆中获取最小元素。
-
Remove Minimum − 从堆中删除最小元素
Insert Operation
-
每当要插入一个元素时。在数组末尾插入元素。将堆的尺寸增加 1。
public void insert(int value) {
size++;
intArray[size - 1] = value;
heapUp(size - 1);
}
private void heapUp(int nodeIndex){
int parentIndex, tmp;
if (nodeIndex != 0) {
parentIndex = getParentIndex(nodeIndex);
if (intArray[parentIndex] > intArray[nodeIndex]) {
tmp = intArray[parentIndex];
intArray[parentIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapUp(parentIndex);
}
}
}
Remove Minimum
-
每当要删除一个元素时。获取数组的最后一个元素,并减少堆的尺寸 1。
public void removeMin() {
intArray[0] = intArray[size - 1];
size--;
if (size > 0)
heapDown(0);
}
private void heapDown(int nodeIndex){
int leftChildIndex, rightChildIndex, minIndex, tmp;
leftChildIndex = getLeftChildIndex(nodeIndex);
rightChildIndex = getRightChildIndex(nodeIndex);
if (rightChildIndex >= size) {
if (leftChildIndex >= size)
return;
else
minIndex = leftChildIndex;
} else {
if (intArray[leftChildIndex] <= intArray[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (intArray[nodeIndex] > intArray[minIndex]) {
tmp = intArray[minIndex];
intArray[minIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapDown(minIndex);
}
}
Heap Implementation
Heap.java
package com.tutorialspoint.datastructure;
public class Heap {
private int[] intArray;
private int size;
public Heap(int size){
intArray = new int[size];
}
public boolean isEmpty(){
return size == 0;
}
public int getMinimum(){
return intArray[0];
}
public int getLeftChildIndex(int nodeIndex){
return 2*nodeIndex +1;
}
public int getRightChildIndex(int nodeIndex){
return 2*nodeIndex +2;
}
public int getParentIndex(int nodeIndex){
return (nodeIndex -1)/2;
}
public boolean isFull(){
return size == intArray.length;
}
public void insert(int value) {
size++;
intArray[size - 1] = value;
heapUp(size - 1);
}
public void removeMin() {
intArray[0] = intArray[size - 1];
size--;
if (size > 0)
heapDown(0);
}
/**
* Heap up the new element,until heap property is broken.
* Steps:
* 1. Compare node's value with parent's value.
* 2. Swap them, If they are in wrong order.
* */
private void heapUp(int nodeIndex){
int parentIndex, tmp;
if (nodeIndex != 0) {
parentIndex = getParentIndex(nodeIndex);
if (intArray[parentIndex] > intArray[nodeIndex]) {
tmp = intArray[parentIndex];
intArray[parentIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapUp(parentIndex);
}
}
}
/**
* Heap down the root element being least in value,until heap property is broken.
* Steps:
* 1.If current node has no children, done.
* 2.If current node has one children and heap property is broken,
* 3.Swap the current node and child node and heap down.
* 4.If current node has one children and heap property is broken, find smaller one
* 5.Swap the current node and child node and heap down.
* */
private void heapDown(int nodeIndex){
int leftChildIndex, rightChildIndex, minIndex, tmp;
leftChildIndex = getLeftChildIndex(nodeIndex);
rightChildIndex = getRightChildIndex(nodeIndex);
if (rightChildIndex >= size) {
if (leftChildIndex >= size)
return;
else
minIndex = leftChildIndex;
} else {
if (intArray[leftChildIndex] <= intArray[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (intArray[nodeIndex] > intArray[minIndex]) {
tmp = intArray[minIndex];
intArray[minIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapDown(minIndex);
}
}
}
Demo Program
HeapDemo.java
package com.tutorialspoint.datastructure;
public class HeapDemo {
public static void main(String[] args){
Heap heap = new Heap(10);
/* 5 //Level 0
*
*/
heap.insert(5);
/* 1 //Level 0
* |
* 5---| //Level 1
*/
heap.insert(1);
/* 1 //Level 0
* |
* 5---|---3 //Level 1
*/
heap.insert(3);
/* 1 //Level 0
* |
* 5---|---3 //Level 1
* |
* 8--| //Level 2
*/
heap.insert(8);
/* 1 //Level 0
* |
* 5---|---3 //Level 1
* |
* 8--|--9 //Level 2
*/
heap.insert(9);
/* 1 //Level 0
* |
* 5---|---3 //Level 1
* | |
* 8--|--9 6--| //Level 2
*/
heap.insert(6);
/* 1 //Level 0
* |
* 5---|---2 //Level 1
* | |
* 8--|--9 6--|--3 //Level 2
*/
heap.insert(2);
System.out.println(heap.getMinimum());
heap.removeMin();
/* 2 //Level 0
* |
* 5---|---3 //Level 1
* | |
* 8--|--9 6--| //Level 2
*/
System.out.println(heap.getMinimum());
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
1
2
DSA using Java - Graph
Overview
图形是一种用于对数学图形进行建模的数据结构。它包含一组连接的成对内容,称为顶点的边。我们可以使用顶点数组和边进行的二维数组来表示图形。
重要术语
-
Vertex - 图形中的各个节点表示为顶点。在下方的范例中,标记的圆圈代表顶点。A 至 G 即顶点。我们可以使用数组来表达它们,如下图所示。此处可以通过索引 0 识别 A。可以通过 1 等识别 B,依此类推。
-
Edge - 边表示两个顶点之间的路径或者两个顶点之间的线。在下方的范例中,从 A 到 B、从 B 到 C 等线表示边。我们可以使用二维数组来表示数组,如下图所示。此处 AB 可以表示为 0 行、1 列中的 1,BC 可以表示为 1 行、2 列中的 1,依此类推,其他组合保持为 0。
-
Adjacency - 两个节点或顶点通过边互相连接,则它们是相邻的。在下方的范例中,B 邻近 A,C 邻近 B,依此类推。
-
Path - 路径表示两个顶点之间的边序列。在下方的范例中,ABCD 表示从 A 到 D 的路径。
Basic Operations
以下是图形的基本主操作。
-
Add Vertex - 向图形添加一个顶点。
-
Add Edge - 在图形的两个顶点之间添加一条边。
-
Display Vertex − 显示图的一个顶点。
Add Vertex Operation
//add vertex to the array of vertex
public void addVertex(char label){
lstVertices[vertexCount++] = new Vertex(label);
}
Add Edge Operation
//add edge to edge array
public void addEdge(int start,int end){
adjMatrix[start][end] = 1;
adjMatrix[end][start] = 1;
}
Display Edge Operation
//display the vertex
public void displayVertex(int vertexIndex){
System.out.print(lstVertices[vertexIndex].label+" ");
}
Depth First Search Algorithm
深度优先搜索算法 (DFS) 以深度方向遍历图并使用一个堆栈记住在任何迭代中发生死锁时获取下一个顶点以开始搜索。
如上例所示,DFS 算法首先从 A 到 B 到 C 到 D,然后到 E,再到 F,最后到 G。它采用以下规则。
-
Rule 1 − 访问相邻的未访问过的顶点。将其标记为已访问。显示它。将其压入堆栈。
-
Rule 2 − 如果找不到相邻顶点,则从堆栈弹出一个顶点。(它会从堆栈中弹出所有没有相邻顶点的顶点。)
-
Rule 3 − 重复规则 1 和规则 2,直到堆栈为空。
public void depthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//push vertex index in stack
stack.push(0);
while(!stack.isEmpty()){
//get the unvisited vertex of vertex which is at top of the stack
int unvisitedVertex = getAdjUnvisitedVertex(stack.peek());
//no adjacent vertex found
if(unvisitedVertex == -1){
stack.pop();
}else{
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
stack.push(unvisitedVertex);
}
}
//stack is empty, search is complete, reset the visited flag
for(int i=0;i<vertexCount;i++){
lstVertices[i].visited = false;
}
}
Breadth First Search Algorithm
广度优先搜索算法 (BFS) 以广度方向遍历图并使用一个队列记住在任何迭代中发生死锁时获取下一个顶点以开始搜索。
如上例所示,BFS 算法首先从 A 到 B 到 E 到 F,然后到 C 和 G,最后到 D。它采用以下规则。
-
Rule 1 − 访问相邻的未访问过的顶点。将其标记为已访问。显示它。将其插入队列。
-
Rule 2 − 如果找不到相邻顶点,则从队列中移除第一个顶点。
-
Rule 3 − 重复规则 1 和规则 2,直到队列为空。
public void breadthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//insert vertex index in queue
queue.insert(0);
int unvisitedVertex;
while(!queue.isEmpty()){
//get the unvisited vertex of vertex which is at front of the queue
int tempVertex = queue.remove();
//no adjacent vertex found
while((unvisitedVertex=getAdjUnvisitedVertex(tempVertex)) != -1){
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
queue.insert(unvisitedVertex);
}
}
//queue is empty, search is complete, reset the visited flag
for(int i=0;i<vertexCount;i++){
lstVertices[i].visited = false;
}
}
Graph Implementation
Stack.java
package com.tutorialspoint.datastructure;
public class Stack {
private int size; // size of the stack
private int[] intArray; // stack storage
private int top; // top of the stack
// Constructor
public Stack(int size){
this.size = size;
intArray = new int[size]; //initialize array
top = -1; //stack is initially empty
}
// Operation : Push
// push item on the top of the stack
public void push(int data) {
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
// Operation : Pop
// pop item from the top of the stack
public int pop() {
//retrieve data and decrement the top by 1
return intArray[top--];
}
// Operation : Peek
// view the data at top of the stack
public int peek() {
//retrieve data from the top
return intArray[top];
}
// Operation : isFull
// return true if stack is full
public boolean isFull(){
return (top == size-1);
}
// Operation : isEmpty
// return true if stack is empty
public boolean isEmpty(){
return (top == -1);
}
}
Queue.java
package com.tutorialspoint.datastructure;
public class Queue {
private final int MAX;
private int[] intArray;
private int front;
private int rear;
private int itemCount;
public Queue(int size){
MAX = size;
intArray = new int[MAX];
front = 0;
rear = -1;
itemCount = 0;
}
public void insert(int data){
if(!isFull()){
if(rear == MAX-1){
rear = -1;
}
intArray[++rear] = data;
itemCount++;
}
}
public int remove(){
int data = intArray[front++];
if(front == MAX){
front = 0;
}
itemCount--;
return data;
}
public int peek(){
return intArray[front];
}
public boolean isEmpty(){
return itemCount == 0;
}
public boolean isFull(){
return itemCount == MAX;
}
public int size(){
return itemCount;
}
}
Vertex.java
package com.tutorialspoint.datastructure;
public class Vertex {
public char label;
public boolean visited;
public Vertex(char label){
this.label = label;
visited = false;
}
}
Graph.java
package com.tutorialspoint.datastructure;
public class Graph {
private final int MAX = 20;
//array of vertices
private Vertex lstVertices[];
//adjacency matrix
private int adjMatrix[][];
//vertex count
private int vertexCount;
private Stack stack;
private Queue queue;
public Graph(){
lstVertices = new Vertex[MAX];
adjMatrix = new int[MAX][MAX];
vertexCount = 0;
stack = new Stack(MAX);
queue = new Queue(MAX);
for(int j=0; j<MAX; j++) // set adjacency
for(int k=0; k<MAX; k++) // matrix to 0
adjMatrix[j][k] = 0;
}
//add vertex to the vertex list
public void addVertex(char label){
lstVertices[vertexCount++] = new Vertex(label);
}
//add edge to edge array
public void addEdge(int start,int end){
adjMatrix[start][end] = 1;
adjMatrix[end][start] = 1;
}
//display the vertex
public void displayVertex(int vertexIndex){
System.out.print(lstVertices[vertexIndex].label+" ");
}
//get the adjacent unvisited vertex
public int getAdjUnvisitedVertex(int vertexIndex){
for(int i=0; i<vertexCount; i++)
if(adjMatrix[vertexIndex][i]==1 && lstVertices[i].visited==false)
return i;
return -1;
}
public void depthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//push vertex index in stack
stack.push(0);
while(!stack.isEmpty()){
//get the unvisited vertex of vertex which is at top of the stack
int unvisitedVertex = getAdjUnvisitedVertex(stack.peek());
//no adjacent vertex found
if(unvisitedVertex == -1){
stack.pop();
}else{
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
stack.push(unvisitedVertex);
}
}
//stack is empty, search is complete, reset the visited flag
for(int i=0;i<vertexCount;i++){
lstVertices[i].visited = false;
}
}
public void breadthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//insert vertex index in queue
queue.insert(0);
int unvisitedVertex;
while(!queue.isEmpty()){
//get the unvisited vertex of vertex which is at front of the queue
int tempVertex = queue.remove();
//no adjacent vertex found
while((unvisitedVertex=getAdjUnvisitedVertex(tempVertex)) != -1){
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
queue.insert(unvisitedVertex);
}
}
//queue is empty, search is complete, reset the visited flag
for(int i=0;i<vertexCount;i++){
lstVertices[i].visited = false;
}
}
}
Demo Program
GraphDemo.java
package com.tutorialspoint.datastructure;
public class GraphDemo {
public static void main(String args[]){
Graph graph = new Graph();
graph.addVertex('A'); //0
graph.addVertex('B'); //1
graph.addVertex('C'); //2
graph.addVertex('D'); //3
graph.addVertex('E'); //4
graph.addVertex('F'); //5
graph.addVertex('G'); //6
/* 1 2 3
* 0 |--B--C--D
* A--|
* |
* | 4
* |-----E
* | 5 6
* | |--F--G
* |--|
*/
graph.addEdge(0, 1); //AB
graph.addEdge(1, 2); //BC
graph.addEdge(2, 3); //CD
graph.addEdge(0, 4); //AC
graph.addEdge(0, 5); //AF
graph.addEdge(5, 6); //FG
System.out.print("Depth First Search: ");
//A B C D E F G
graph.depthFirstSearch();
System.out.println("");
System.out.print("Breadth First Search: ");
//A B E F C G D
graph.breadthFirstSearch();
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Depth First Search: A B C D E F G
Breadth First Search: A B E F C G D
DSA using Java - Search techniques
搜索是指在项目集合中找到指定属性的所需元素。我们将使用以下常用的简单搜索算法开始我们的讨论。
Sr.No |
Technique & Description |
1 |
Linear Search 线性搜索搜索所有项目,其最差执行时间为 n,其中 n 是项目数量。 |
2 |
Binary Search 二分搜索要求项目按顺序排列,但其最差执行时间是常数,并且比线性搜索快得多。 |
3 |
Interpolation Search 插值搜索要求项目按顺序排列,但其最差执行时间为 O(n),其中 n 是项目数量,并且比线性搜索快得多。 |
DSA using Java - Sorting techniques
排序是指以特定格式排列数据。排序算法指定了以特定顺序排列数据的途径。最常见的顺序是数字顺序或字典顺序。
排序的重要性在于,如果以排序的方式存储数据,则可以将数据搜索优化到很高水平。排序也可用于以更具可读性的格式表示数据。以下是在现实生活场景中排序的一些示例。
-
Telephone Directory − 电话号码簿将人们的电话号码按照他们的姓名顺序排列。以便可以搜索名称。
-
Dictionary − 字典将单词按字母顺序排列,以便在任何工作中找到它。
Types of Sorting
以下是流行排序算法及其比较的列表。
Sr.No |
Technique & Description |
1 |
Bubble Sort 冒泡排序是一种理解和实现算法的简单方法,但在性能上很差。 |
2 |
Selection Sort 选择排序,正如名称所指定的那样,使用技术来选择所需项目并相应地准备排序数组。 |
3 |
Insertion Sort 插入排序是选择排序的一个变种。 |
4 |
Shell Sort 希尔排序是插入排序的高效版本。 |
5 |
Quick Sort 快速排序是一种高效的排序算法,它基于将数据数组分成更小的数组。 |
6 |
Sorting Objects 可以使用 java.util.Arrays.sort() 来轻松地对 Java 对象进行排序。 |
DSA using Java - Recursion
Recursive Factorial
阶乘是递归的一个经典示例。阶乘是一个满足以下条件的非负数。
阶乘表示为“!”。此处规则 1 和规则 2 是基本情况,而规则 3 是阶乘规则。
例如,3! = 3 x 2 x 1 = 6
private int factorial(int n){
//base case
if(n == 0){
return 1;
}else{
return n * factorial(n-1);
}
}
Recursive Fibonacci Series
斐波那契数列是递归的另一个经典示例。斐波那契数列是一个满足以下条件的整数数列。
斐波那契表示为“F”。此处规则 1 和规则 2 是基本情况,而规则 3 是斐波那契规则。
例如,F5 = 0 1 1 2 3
Demo Program
RecursionDemo.java
package com.tutorialspoint.algorithm;
public class RecursionDemo {
public static void main(String[] args){
RecursionDemo recursionDemo = new RecursionDemo();
int n = 5;
System.out.println("Factorial of " + n + ": "
+ recursionDemo.factorial(n));
System.out.print("Fibbonacci of " + n + ": ");
for(int i=0;i<n;i++){
System.out.print(recursionDemo.fibbonacci(i) +" ");
}
}
private int factorial(int n){
//base case
if(n == 0){
return 1;
}else{
return n * factorial(n-1);
}
}
private int fibbonacci(int n){
if(n ==0){
return 0;
}
else if(n==1){
return 1;
}
else {
return (fibbonacci(n-1) + fibbonacci(n-2));
}
}
}
如果我们编译并运行上述程序,它将生成以下结果 -
Factorial of 5: 120
Fibbonacci of 5: 0 1 1 2 3