1.单、双链表结构,以及对链表的反转、删除链表中的某个值
双链表节点结构:
public class DoubleNode {
int value;
public DoubleNode before;
public DoubleNode next;
public DoubleNode(int value) {
this.value = value;
}
}
单链表节点结构:
public class Node {
int value;
public Node next;
public Node(int value){
this.value = value;
}
}
示例代码(我写的草稿不太完善):
public class Reverse {
//单链表反转
public static Node reverse(Node head){
Node pre = null;
Node next = null;
while (head != null) {
next = head.next; // 记录head的下一个节点
head.next = pre;
pre = head; //记录此时的头节点
head = next; //往下一个节点跳
}
return pre;
}
//双链表反转
public static DoubleNode reverse(DoubleNode head){
DoubleNode pre = null;
DoubleNode next = null;
while (head != null){
next = head.next; //记录head的下一个节点
head.next = pre;
head.before = next;
pre = head;
head = next;
}
return pre;
}
//删除单链表的一个值
//TODO: 这需要写出删除所有相同的值
public static Node delete(Node head,int num){
Node pre = null;
Node newHead = head;
if(head == null){
return newHead;
}
while (head!=null){
if(head.value == num){
if(pre!=null) {
pre.next = head.next;
head.next = null;
return newHead;
}
if(pre == null){
pre = head.next;
head.next = null;
return pre;
}
}
pre = head;
head = head.next;
}
return newHead;
}
//删除双链表的一个值
//TODO: 这需要写出删除所有相同的值
public static DoubleNode delete(DoubleNode head,int num){
DoubleNode newHead = head;
DoubleNode preHead = null;
DoubleNode afterHead = null;
while (head!=null){
if(head.value==num){
if(preHead != null){
if(head.next!=null) {
afterHead = head.next;
afterHead.before = preHead;
}
preHead.next = afterHead;
head.before = null;
head.next = null;
return newHead;
}
if(preHead == null){
newHead = head.next;
head.next = null;
newHead.before = null;
return newHead;
}
}
preHead = head;
head = head.next;
}
return newHead;
}
//打印单链表
public static void print(Node head){
Node next = head;
while (next!=null){
System.out.println(next.value);
next = next.next;
}
}
//打印双链表
public static void print1(DoubleNode head){
DoubleNode next = head;
while (next!=null){
System.out.println(next.value);
next = next.next;
}
}
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
node1.next = node2;
node2.next = node3;
print(node1);
Node reverse = delete(node1,3);
System.out.println("反转后....");
print(reverse);
DoubleNode node4 = new DoubleNode(1);
DoubleNode node5 = new DoubleNode(2);
DoubleNode node6 = new DoubleNode(3);
node4.before = null;
node4.next = node5;
node5.before = node4;
node5.next = node6;
node6.before = node5;
node6.next = null;
System.out.println("========================================");
print1(node4);
DoubleNode reverse1 = delete(node4,2);
System.out.println("反转后....");
print1(reverse1);
}
}
2.我们要明白计算机底层的真实物理数据结构只有数组和链表,其他任何数据结构都是假的,都是人为造的,都是通过数组和链表来实现的一种合金结构。
分别用双向链表和数组实现栈和队列:
双向链表:
public class MyLinked {
public DoubleNode head = null;
public DoubleNode tail = null;
//从头部增加一个数
public void addFromHead(int num){
if(head == null){
DoubleNode node = new DoubleNode(num);
head = node;
tail = node;
}else{
DoubleNode node = new DoubleNode(num);
node.next = head;
head.before = node;
head = node;
}
}
//从尾部增加一个数
public void addFromTail(int num){
if(head == null){
DoubleNode node = new DoubleNode(num);
head = node;
tail = node;
}else{
DoubleNode node = new DoubleNode(num);
tail.next = node;
node.before = tail;
tail = node;
}
}
//从头部删除一个数
public void deleteFromHead(){
if(head != null){
DoubleNode next = head.next;
next.before = null;
head.next = null;
head = next;
}
}
//从尾部删除一个数,想找到尾部节点的上一个节点,单链表比较复杂,因此采用双链表
public void deleteFromTail(){
if(head != null){
DoubleNode before = tail.before;
before.next = null;
tail.before = null;
tail = before;
}
}
}
用双向链表实现栈和队列:
//用链表和数组实现队列
public class MyQueue {
private static MyLinked myLinked = new MyLinked();
//队列,从尾部进,从头部出,先进先出
public void add(int num){
myLinked.addFromTail(num);
}
public void pop(){
myLinked.deleteFromHead();
}
}
//用链表和数组实现栈
public class MyStack {
private static MyLinked myLinked = new MyLinked();
//栈,从尾部进,从尾部出,先进后出
public void add(int num){
myLinked.addFromTail(num);
}
public void pop(){
myLinked.deleteFromTail();
}
}
用数组实现栈和队列(写了个草稿不完善):
//TODO: 这需要写成一个环形数组
public class MyQueue1 {
private static int[] innerArr = {};
private int head;
private int tail;
public void add(int num){
innerArr[tail] = num;
tail++;
}
public int pop(){
int num = innerArr[head];
head--;
return num;
}
}
public class MyStack1 {
private static int[] innerArr = {};
private int index;
public void add(int num){
innerArr[index] = num;
index++;
}
public int pop(){
int num = innerArr[index];
index--;
return num;
}
}
3.实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能
/**
* 实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能
* 要求:
* 1.pop,push,getMin操作的时间复杂度都是o(1)
* 2.设计的栈类型可以使用现成的栈结构
*/
public class Task1 {
public static void main(String[] args) throws Exception {
//用双向链表实现栈
MyStackOfMinValue myStackOfMinValue = new MyStackOfMinValue();
myStackOfMinValue.push(2);
myStackOfMinValue.push(3);
myStackOfMinValue.push(2);
myStackOfMinValue.push(3);
int pop = myStackOfMinValue.pop();
System.out.println("pop = " + pop);
int min = myStackOfMinValue.getMin();
System.out.println("min = " + min);
}
}
class MyStackOfMinValue{
private static final MyStack myStack1 = new MyStack();
private static final MyStack myStack2 = new MyStack();
//当插入一个数时
void push(int num) throws Exception{
if(myStack1.isEmpty()){
myStack1.push(num);
myStack2.push(num);
}else{
myStack1.push(num);
if(myStack2.stackTop() >= num){
myStack2.push(num);
}
}
}
//当弹出一个数时
int pop() throws Exception{
int pop = myStack1.pop();
if(myStack2.stackTop() == pop){
myStack1.pop();
}
return pop;
}
//获取最小值
int getMin() throws Exception{
return myStack2.stackTop();
}
}
class MyStack{
private MyLinked myLinked = new MyLinked();
//栈是先进后出,从尾部插入,从尾部取出
void push(int num){
myLinked.insertFromTail(num);
}
int pop() throws Exception{
return myLinked.getFromTail();
}
boolean isEmpty(){
return myLinked.head == null;
}
//查看栈顶元素
int stackTop() throws Exception{
if(isEmpty()){
throw new Exception("栈中没有元素!");
}
return myLinked.tail.value;
}
}
class DoubleNode{
DoubleNode pre;
DoubleNode next;
int value;
}
class MyLinked{
DoubleNode head=null;
DoubleNode tail=null;
//从头部插入
void insertFromHead(int num){
if(head == null){
DoubleNode doubleNode = new DoubleNode();
doubleNode.value = num;
head = doubleNode;
tail = doubleNode;
}else{
DoubleNode doubleNode = new DoubleNode();
doubleNode.value = num;
doubleNode.next = head;
head = doubleNode;
}
}
//从尾部插入
void insertFromTail(int num){
if(tail == null){
DoubleNode doubleNode = new DoubleNode();
doubleNode.value = num;
head = doubleNode;
tail = doubleNode;
}else{
DoubleNode doubleNode = new DoubleNode();
doubleNode.value = num;
tail.next = doubleNode;
tail = doubleNode;
}
}
//从头部弹出一个数
int getFromHead() throws Exception{
if(head==null){
throw new Exception("没有元素可以获取!");
}else{
int num = head.value;
head = head.next;
return num;
}
}
//从尾部弹出一个数
int getFromTail() throws Exception{
if(tail == null){
throw new Exception("没有元素可以获取!");
}else{
int num = tail.value;
tail = tail.pre;
if(tail!=null) {
tail.next = null;
}
return num;
}
}
}
4,如果只给你队列结构怎么实现栈,如果只给你栈结构怎么实现队列?
/**
* 1.如何用栈结构实现队列结构
* 2。如何用队列结构实现栈结构
*/
public class Task2 {
public static void main(String[] args) throws Exception{
/*MyStack2 myStack2 = new MyStack2();
myStack2.push(1);
myStack2.push(2);
myStack2.push(3);
myStack2.push(4);
myStack2.push(5);
int pop = myStack2.pop();
System.out.println("pop = " + pop);
myStack2.push(6);
int pop1 = myStack2.pop();
System.out.println("pop1 = " + pop1);*/
MyQueue2 myQueue2 = new MyQueue2();
myQueue2.add(1);
myQueue2.add(2);
myQueue2.add(3);
myQueue2.add(4);
myQueue2.add(5);
int remove = myQueue2.remove();
System.out.println("remove = " + remove);
myQueue2.add(6);
int remove1 = myQueue2.remove();
System.out.println("remove1 = " + remove1);
}
}
/**
* 栈:先进后出
* 用队列模仿栈,入队和入栈一样,出栈的话用队列模拟就是要把最后一个值取出来,出队列。
* 思路:搞两个队列,每次要模拟出栈的时候,将队列出列到另一个空队列中,直到队列中只剩余一个值,将这个值出队就是出栈。
*/
class MyStack2{
private Queue dataQueue = new LinkedBlockingQueue();
private Queue subQueue = new LinkedBlockingQueue();
public void push(int num){
if(dataQueue.size()==0 && subQueue.size() == 0){
dataQueue.add(num);
}else if(dataQueue.size() > 0){
dataQueue.add(num);
}else{
subQueue.add(num);
}
}
public int pop() throws Exception{
if(dataQueue.size() == 0 && subQueue.size() == 0){
throw new Exception("栈里没有元素!");
}
if(dataQueue.size() > 0){
while (dataQueue.size() > 1){
Object poll = dataQueue.poll();
subQueue.add(poll);
}
return (Integer) dataQueue.poll();
}else{
while (subQueue.size() > 1){
Object poll = subQueue.poll();
dataQueue.add(poll);
}
return (Integer) subQueue.poll();
}
}
}
/**
* 队列:先进先出
* 用栈模拟队列,入队和入栈一样,出队的话用栈模拟就是要·把第一个值取出来出栈。
* 思路:搞两个栈,每次要模拟出队的时候,将栈出栈到另一个空栈中,直到栈中只剩余一个值,将这个值出栈后,再将另一个栈的数据出栈入到这个栈中就是出队。
*/
class MyQueue2{
private Stack dataStack = new Stack();
private Stack preStack = new Stack();
public void add(int num){
dataStack.push(num);
}
public int remove() throws Exception{
if(dataStack.isEmpty()){
throw new Exception("队列中没有元素");
}
while (!dataStack.isEmpty()){
preStack.push(dataStack.pop());
}
Object pop = preStack.pop();
while (!preStack.isEmpty()){
dataStack.push(preStack.pop());
}
return (Integer) pop;
}
}