2021.12.26
第 11 天: 顺序表
日志:完成了对顺序表的创建,我发现自己还是没有明白对象到底该怎么用,感觉这个和c语言的结构体差不多,但又差很多。。。
将顺序表相关操作全部在这个类中实现,以后创建对象时,对象就可以用相关操作了。
package basic;
public class SequentialList {
public static final int MAX_LENGTH = 10;// 定义顺序表最大值,是常数
int length;
int[] data;
public SequentialList() {
length = 0;
data = new int[MAX_LENGTH];
}// 无参构造
public SequentialList(int[] arr) {
data = new int[MAX_LENGTH];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
length++;
} // 有参构造
}
public void reset() {
length = 0;
}
public String toString() {
if (length <= 0) {
return "当前没有元素";
}
String resultString = "元素:";
for (int i = 0; i < length; i++) {
resultString += data[i] + ",";// String的用法????
}
return resultString;
}
public static void main(String[] args) {// 对这个顺序表进行测试
int[] a = { 1, 2, 3, 4 };
SequentialList SqList = new SequentialList(a);
System.out.println("当前顺序表长度:" + SqList.length);
System.out.println("当前所存在的" + SqList.toString());
SqList.reset();
System.out.println("当前顺序表长度:" + SqList.length);
System.out.println("当前所存在的元素:" + SqList.toString());
}
}
继续:以上实现了顺序表的创建和清除(也就是长度设为0罢了),继续实现在特定位置插入和删除数据。这里的话一旦数据超出了顺序表的范围,就会提醒出错,不会把数据加入数据表。在进行数据删除和添加时,还要关注顺序表为空和为满的情况。(稍后再来继续写。。。。)
更新后代码:增加了顺序表插入,删除,查找元素的基本功能。
搭建了顺序表基本框架,实现功能就很简单了。
package basic;
public class SequentialList {
public static final int MAX_LENGTH = 10;// 定义顺序表最大值,是常数
int length;
int[] data;
public SequentialList() {
length = 0;
data = new int[MAX_LENGTH];
}// 无参构造
public SequentialList(int[] arr) {
data = new int[MAX_LENGTH];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
length++;
} // 有参构造
}
public void reset() {
length = 0;
System.out.println("顺序表已清空");
}
public String toString() {
if (length <= 0) {
return "当前没有元素";
}
String resultString = "";
for (int i = 0; i < length; i++) {
if (i == 0)
resultString += data[i];
else
resultString += "," + data[i];// String的用法????
}
return resultString;
}
public void AddElem(int location, int elem) {// 位置 要插入的元素
if (length == MAX_LENGTH) {
System.out.println("顺序表已满!");
return;
}
if (location <= 0 || location > length + 1) {
System.out.println("输入不合法,请重新输入");
return;
}
for (int i = length - 1; i >= location - 1; i--) {
data[i + 1] = data[i];
}
data[location - 1] = elem;
length++;
System.out.println("插入成功!");
}// 向指定位置添加元素
public int DeleteElem(int location) {
if (length == 0) {
System.out.println("顺序表已空,删除失败!");
return -1;
}
if (location <= 0 || location > length) {
System.out.println("输入不合法,请重新输入");
return -1;
}
for (int i = location - 1; i < length; i++) {
data[i] = data[i + 1];
}
length--;
return data[location - 1];
}// 删除指定位置的元素
public int GetIndex(int num) {
if (length <= 0) {
return -1;
}
if (num <= 0 || num > length) {
return -1;
}
int flag = 0;// 查找判定
return data[num - 1];
}// 获取对应位置的元素
public static void main(String[] args) {// 对这个顺序表进行测试
int[] a = { 1, 2, 3, 4 };
SequentialList SqList = new SequentialList(a);
System.out.println("当前顺序表长度:" + SqList.length);
System.out.println("当前所存在的元素:" + SqList.toString());
SqList.reset();
System.out.println("当前顺序表长度:" + SqList.length);
System.out.println("当前所存在的元素:" + SqList.toString());
SqList.AddElem(1, 18);
SqList.AddElem(1, 90);
SqList.AddElem(2, 100);
System.out.println("当前所存在的元素:" + SqList.toString());
SqList.reset();
System.out.println("当前所存在的元素:" + SqList.toString());
SqList.DeleteElem(1);
System.out.println("当前所存在的元素:" + SqList.toString());
}
}
当前顺序表长度:4
当前所存在的元素:1,2,3,4
顺序表已清空
当前顺序表长度:0
当前所存在的元素:当前没有元素
插入成功!
插入成功!
插入成功!
当前所存在的元素:90,100,18
顺序表已清空
当前所存在的元素:当前没有元素
顺序表已空,删除失败!
当前所存在的元素:当前没有元素
基本数据结构顺序表,删除和添加会比较麻烦,不过查找起来却很轻松。
2021.12.27:
继续链表操作:
支持与顺序表相同的操作: 初始化、插入、删除等.
1 为节点建一个类.
2 引用与指针的异同. 前者只能使用; 后者可以支持 p ++ 危险操作.
3 引用数据类型的赋值, 都不会产生新的对象空间.
4 链表与线性表在插入、删除时的不同: 前者不移动元素, 只改变引用 (指针).
终于有时间了,我把接下来的链表基本功能进行了完善,目前有如下功能:
1:头插,尾插数据。指定位置插入数据。
2:遍历链表。获得链表长度。
3:删除指定位置元素。清空链表。
在做的的时候我在想java它有自动回收,那当我清空链表时,将head指向null,不知道回收机制会不会回收掉之后的内容,我下去再看看。
package basic;
//本次含有头结点。
public class LinkedList {
static Node head = new Node();// 定义头结点,本处头结点供所有方法进行使用,因此加上static
public void TailAdd(int elem) {
Node newnode = new Node(elem);
Node temp = head;
while (temp.next != null) {
temp = temp.next;
} // 遍历搜寻最后一个节点位置
temp.next = newnode;
// System.out.println("插入成功!");
/*
* while(temp != null) { temp = temp.next; } temp = newnode;//感觉和c语言有很大不同,等下再看看
*/
}// 尾插法插入
public void HeadAdd(int elem) {
Node temp = head;
Node newnode = new Node(elem);
newnode.next = temp.next;
temp.next = newnode;
// System.out.println("插入成功!");
}// 头插法插入
public void IndexAdd(int index, int elem) {
if (index <= 0 || index > ElemNum() + 1) {
System.out.println("输入不合法,插入失败!");
return;
}
Node pre = head;
Node cur = head.next;
Node newnode = new Node(elem);
for (int i = 1; i <= index - 1; i++) {
cur = cur.next;
pre = pre.next;
}
pre.next = newnode;
newnode.next = cur;
System.out.println("插入成功!");
}// 指定位置插入
public void Delete(int index) {
if (head.next == null) {
System.out.println("当前链表无元素!");
return;
}
if (index <= 0 || index > ElemNum()) {
System.out.println("输入不合法,删除失败!");
return;
}
Node pre = head;// 标记删除节点的前一个节点
Node cur = head.next;// 标记删除节点
for (int i = 1; i <= index - 1; i++) {
cur = cur.next;
pre = pre.next;
}
pre.next = cur.next;
System.out.println("删除了第" + index + "个元素!");
}// 指定位置删除节点
public static int ElemNum() {
int num = 0;
if (head.next == null) {
return num;
}
Node temp = head.next;
while (temp != null) {
num++;
temp = temp.next;
}
return num;
}
public void Reverse() {
if (head.next == null) {
System.out.println("链表为空!");
return;
}
Node temp = head.next;
System.out.print("当前元素有:");
while (temp != null) {
System.out.print(temp.elem + " ");
temp = temp.next;
}
System.out.println("");
}// 遍历查询
public void DeleteAll() {
head.next = null;
System.out.println("链表已清空");
}// 删除所有节点
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.TailAdd(1);
list.TailAdd(3);
list.TailAdd(5);
list.TailAdd(6);
list.IndexAdd(1, 80);
list.IndexAdd(2, 99);
System.out.println("当前元素个数:" + list.ElemNum());
list.Reverse();
list.Delete(2);
list.Reverse();
list.HeadAdd(9);
list.HeadAdd(12);
list.Reverse();
}// main方法进行链表测试
}
class Node {// 添加节点类,存储数据和指向下一个的引用(这里存储int类型)
int elem;
Node next;
public Node() {// 初始化节点
elem = 0;
// next = null;
}
public Node(int elem) {
this.elem = elem;
// next = null;
}
}
当前元素个数:6
当前元素有:80 99 1 3 5 6
删除了第2个元素!
当前元素有:80 1 3 5 6
当前元素有:12 9 80 1 3 5 6
链表删除添加元素很轻松,遍历起来就稍微有点麻烦了。基本数据结构,实现难度小。
有时间再来补充接下来的内容吧,哈哈。
2021.12.28
栈
push 和 pop 均只能在栈顶操作.
没有循环, 时间复杂度为 O ( 1 )
栈元素先入后出,明白顺序表怎么写的话,这个写起来就很简单了。代码如下:
package basic;
public class Stack {
//这里我就默认外部输入的数组长度是小于MAX_SIZE了,就不加条件判断了。
public static final int MAX_SIZE=10;//定义顺序栈容量
int []data;//栈中数组。
int length = 0;//当前栈中元素数量。
public Stack() {
data = new int[MAX_SIZE];
}
public Stack(int[] arr) {
data = new int[arr.length];
length = arr.length;
for(int i =0;i<length;i++) {
data[i] = arr[i];
}
}
public void push(int elem) {
if(length>=MAX_SIZE) {
System.out.println("当前栈已满,添加失败!");
return;
}
data[length++] = elem;
}//压栈
public int pop() {
if(length<=0) {
System.out.println("当前栈已空,删除失败!");
return -101010;
}
int temp = data[length-1];
length--;
return temp;
}//弹栈
public int ElemNum() {
return length;
}//当前栈元素数
public void Reverse() {
if(length<=0) {
System.out.println("栈为空!");
return;
}
System.out.print("当前栈中元素:");
for(int i = 0;i<length;i++) {
System.out.print(data[i]+" ");
}
System.out.println("");
}
public static void main(String[] args) {
int []a = {1,2,4,5,6};
Stack st = new Stack(a);
st.Reverse();
st.pop();
st.Reverse();
st.pop();
st.Reverse();
st.pop();
st.Reverse();
st.pop();
st.Reverse();
st.pop();
st.Reverse();
st.push(1);
st.Reverse();
st.push(2);
st.Reverse();
st.push(3);
st.Reverse();
st.push(4);
st.Reverse();
st.push(5);
st.Reverse();
}//main方法进行测试
}
当前栈中元素:1 2 4 5 6
当前栈中元素:1 2 4 5
当前栈中元素:1 2 4
当前栈中元素:1 2
当前栈中元素:1
栈为空!
当前栈中元素:1
当前栈中元素:1 2
当前栈中元素:1 2 3
当前栈中元素:1 2 3 4
当前栈中元素:1 2 3 4 5
2021.12.30
栈的应用,进行括号匹配
整个代码最需要注意的地方就是switch当中不使用break的话,会继续执行接下来的代码,会导致结果错误。只需要将括号放入栈,之后遇到不同的括号,进行匹配。每次匹配前弹栈。这样做的好处,就算遇到不符合的情况,直接返回false,无需再去计算。
package basic;
public class BracketMatching {
//这里我就默认外部输入的数组长度是小于MAX_SIZE了,就不加条件判断了。
public static final int MAX_SIZE=20;//定义顺序栈容量
char []data;//栈中数组。
int length = 0;//当前栈中元素数量。
public BracketMatching() {
data = new char[MAX_SIZE];
}
public void push(char elem) {
if(length>=MAX_SIZE) {
System.out.println("当前栈已满,添加失败!");
return;
}
data[length++] = elem;
}//压栈
public char pop() {
if(length<=0) {
// System.out.println("当前栈已空,删除失败!");
return '?';
}
char temp = data[length-1];
length--;
return temp;
}//弹栈
public char GetTop() {
return data[length-1];
}//获取顶部元素
public int ElemNum() {
return length;
}//当前栈元素数
public void Reverse() {
if(length<=0) {
System.out.println("栈为空!");
return;
}
System.out.print("当前栈中元素:");
for(int i = 0;i<length;i++) {
System.out.print(data[i]+" ");
}
System.out.println("");
}
public boolean BracketMatchingMethod(String arr) {
BracketMatching brack = new BracketMatching();//单独判断的话就随便建一个吧,无所谓
char temp,poptemp;
if(arr.length()==0) return false;
for(int i = 0;i<arr.length();i++) {
temp = arr.charAt(i);
switch(temp) {//如果全输入左边部分,不进行判断直接压栈
//采用
case '[':
case '{':
case '(':
brack.push(temp);
break;
case ']':
poptemp = brack.pop();//不采用break的话,后面的pop会继续执行,整个代码最需要注意的地方应该就是这里了
if(poptemp!='[') {
return false;
}
break;
case '}':
poptemp = brack.pop();
if(poptemp!='{') {
return false;
}
break;
case ')':
poptemp = brack.pop();
if(poptemp!='(') {
return false;
}
break;
default:
}
}
if(brack.ElemNum()!=0) return false;
else return true;
}
public static void main(String[] args) {
int []a = {1,2,4,5,6};
BracketMatching st = new BracketMatching();
String test = "[]12[fds] {(fijo)}";
boolean result = st.BracketMatchingMethod(test);
System.out.println(result);
test = "[[]}";
System.out.println(st.BracketMatchingMethod(test));
}//main方法进行测试
}
true
false