您的位置:首页 > 编程语言 > Java开发

算法学习笔记 第2章 栈、队列、链表

2016-08-12 07:54 369 查看
目录:



队列

链表

小发现

[实例]判断一个字符串是否为回文 具体说明:

所谓回文字符串就是指正读反读均相同的字符序列,如"大哥大"、"ahaha"均是回文,但"ahah"不是回文。


用栈解决这个问题的代码:

import java.util.Arrays;
import java.util.Scanner;

/**
* <p>Description:判断一个字符串是否为回文</p>
* <p>2016年8月8日 下午4:24:23</p>
* @author  wdk
* @version 1.0
*/
public class PalindromeJudge {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一行字符串:");
String str = sc.nextLine();
int len = str.length();//字符串的长度
//将字符存入数组
char[] arr = str.toCharArray();
int mid = len >> 1;//字符串的中点  等价于    int mid = len / 2
char[] stack = new char[mid];
int top = -1;//栈初始化
//将arr数组中点前的字符压入栈中
for (int i = 0; i < mid; i++) {
stack[++top] = arr[i];
}
//判断字符串的长度是奇数还是偶数,以此决定arr数组从哪个位置开始对比(如果是奇数,则从中点的下个位置开始,即mid + 1)
int next = (len % 2 == 0) ? mid : mid + 1;
//判断arr数组后半部分与压入栈中的值(arr数组前半部分)是否一一对应
for (int i = next; i <= len - 1; i++) {
if(arr[i] != stack[top])
{
break;//如果不等,则立刻结束本层循环
}
top--;//出栈
}
//如果栈为空,也就是说arr数组后半部分与压入栈中的值一一对应了,则该字符串为回文
if(top == -1)
{
System.out.println("YES");
}
else
{
System.out.println("NO");
}
//System.out.println(top);//打印当前top值
//System.out.println(Arrays.toString(stack));//打印栈中的值
}
}


解析:

栈是后进先出的数据结构,栈限定为只能在一端进行插入和删除操作。栈的实现需要一个一维数组和一个指向栈顶的变量top,通过top来对栈进行插入和删除操作。

本实例中,先将mid之前的字符全部入栈了;初始化栈是:top = 0; 入栈是top++;arr[top] = x ;(假设需要入栈的字符暂存在字符变量x中),可简写为arr[++top] = x; 出栈是top–;

队列

[实例]用队列解密QQ号 规则如下:

首先将第1个数删除,紧接着将第2个数放到这串数的末尾,
再将第3个数删除并将第4 个数放到这串数的末尾,
再将第5个数删除.....
直至剩下最后一个数,将最后一个数也删除。
按照刚才删除的顺序,把这些删除的数连在一起就是我们要得到的QQ号。
现在给定一串加密过的数是"6 3 1 7 5 8 9 2 4",经过以上规则解密后,得到的QQ号为:" 6 1 5 9 4  7 2 8 3"


用队列模拟解密过程的代码:

class MyQueue2{
private int[] arr;
private int head = 1;//队首
private int tail = 1;//队尾

public int getHead() {
return head;
}
public int getTail() {
return tail;
}

public MyQueue2() {
this(50);
}
public MyQueue2(int max) {
arr = new int[max];
}
/**
* 从队尾插入数据
* @param value
*/
public void insert(int value) {
arr[tail] = value;
tail++;
}
/**
* 从队头删除数据
*/
public void delete(){
head++;
}
/**
* 从队头查看数据
* @return
*/
public int peek(){
return arr[head];
}
}
/**
*
* <p>Description:用队列解密QQ号</p>
* <p>2016年8月6日 下午4:07:57</p>
* @author  wdk
* @version 3.0
*/
public class QueueDecodeQQ3 {
public static void main(String[] args) {
MyQueue2 queue = new MyQueue2();
int[] arr = new int[]{6,3,1,7,5,8,9,2,4};
for (int a : arr) {
queue.insert(a);
}
while(queue.getHead() < queue.getTail()){
//打印队首,并将队首出列
System.out.print(queue.peek() + " ");
queue.delete();
//先将新队首的数添加到队尾
queue.insert(queue.peek());
//再将队首出队
queue.delete();
}
}
}


解析:

队列是一种特殊的线性结构,它只允许在队列的首部(head)进行删除操作,这称为”出队”,而在队列的尾部(tail)进行插入操作,这称为”入队”。当队列中没有元素时(即head == tail),称为空队列。

本实例中,有9个数,9个数全部放入队列后head = 1;tail = 10;此时head和tail之间的数就是目前队列”有效”的数。如果要删除一个数,就将head++;如果新增加一个数,就是把需要增加的数放到队尾即arr[tail],之后再tail++即可。

图示如下:

a)在队首删除一个数的操作:head++



b)在队尾增加一个数(假设这个数是x)的操作:q[tail] = x ; tail ++;



c)以下是解密全过程:



链表

[实例]链表的实现 代码演示:

import java.util.Scanner;
//定义一个结点类型
class Node{
int data;
Node next;
}
/**
* <p>Description:链表的实现(插入与查询)</p>
* <p>2016年8月9日 下午4:45:40</p>
* @author  wdk
* @version 1.0
*/
public class LinkedList {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要读入的个数:");
int n = sc.nextInt();
System.out.println("请依次输入"+ n +"个整数(eg. 2 4 6 ...):");

int[] a = new int
;
Node head = null;//链表还没创建的时候头指针为空(即:头指针指向空结点)
Node oldNode = null;
Node newNode = null;
Node temp;
/* 在头结点后插入n个结点*/
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
newNode = new Node();//每循环一次创建一个结点
newNode.data = a[i];//将数据存储到当前结点的data域中
newNode.next = null;//设置当前结点的后继指针为空,也就是当前结点的下一结点为空
if(head == null)
{
//如果这是第一个创建的结点,则将头指针指向这个结点
head = newNode;
}
else
{
//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
oldNode.next = newNode;
}
//最后指针oldNode也指向当前结点,因为待会儿临时指针newNode会指向新创建的结点
oldNode = newNode;
}
System.out.println("再补充插入一个值:");
int insertValue = sc.nextInt();
temp = head;//从链表头部开始遍历
while(temp != null)//当没有到达链表尾部的时候循环
{
//如果当前结点是最后一个结点或者下一个结点的值大于待插入数的时候插入
if(temp.next == null || temp.next.data > insertValue)
{
newNode = new Node();
newNode.data = insertValue;//将数据存储到新增结点的data域中
newNode.next = temp.next;//新增结点的后继指针指向当前结点的后继指针所指向的结点
temp.next = newNode;//当前结点的后继指针指向新增结点
break;//插入完毕退出循环
}
temp = temp.next;//继续下一个结点
}

/* 输出链表中所有的数*/
temp = head;//从链表头部开始遍历
System.out.println("链表里的值依次为:");
while(temp != null)//当没有到达链表尾部的时候循环
{
System.out.print(temp.data + " ");//打印数据域
temp = temp.next;//继续下一结点
}

}
}/*Output:
请输入要读入的个数:
4
请依次输入4个整数(eg. 2 4 6 ...):
1 3 4 6
再补充插入一个值:
5
链表里的值依次为:
1 3 4 5 6
*/


图示解析:

a)创建结点的操作演示:



b)往链表插入值的演示:



小发现

关于循环截止值以及初始化值等取值是不固定的,根据具体情况分析,可以先估计这写出来,然后再调试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 链表 队列 Java