1.顺序存储结构
顺序存储结构,即数组。优点:节省存储空间,随机存取表中元素;缺点 :插入和删除操作需要移动元素
顺序存储结构的插入与删除操作代码实现
public void insert(int data){
if (length >= size){
System.out.println("已存满");
return;
}
if (0 == length){
datas[length++] = data;
return;
}
int location = length;
for (int i=0;i<length;i++){
if (datas[i] > data){
location = i;
break;
}
}
for (int i=length-1;i>=location;i--){
datas[i+1] = datas[i];
}
datas[location] = data;
length++;
}
public void remove(int data){
if (0 == length){
System.out.println("空的链表");
return;
}
int location = -1;
for(int i=0;i<length;i++){
if (datas[i] == data){
location = i;
break;
}
}
if (location == -1){
System.out.println(data+" 不存在");
return;
}
for (int i=location;i<length-1;i++){
datas[i] = datas[i+1];
}
length--;
}
2.链式存储结构
链式存储结构:用一组任意的存储单元存储线性表的数据元素,分为单链表、双链表、循环链表。逻辑上相邻的节点物理上不必相邻,每个结点是由数据域和指针域组成。
链式存储结构的优点: 插入、删除开销小(不必移动节点,只要改变节点中的指针)。缺点 :查找结点时链式存储要比顺序存储慢。
单链表的插入删除、链表逆置、判断有环
//插入
public void insert (int data){
Node node = new Node(data,null);
if (null == this.head){
this.head = node;
return;
}
//若插入节点小于头节点,则设置新插入节点为头节点
if (head.getData() > data){
node.setNext(this.head);
this.head = node;
return;
}
//记录头节点位置
Node p = head;
//从头节点开始寻找大于data的位置
while(null != p.getNext()){
if (p.getNext().getData() > data){
break;
}
//下一个节点
p = p.getNext();
}
//插入节点
node.setNext(p.getNext());
p.setNext(node);
}
//删除
public void remove(int data){
if (null == this.head ){
System.out.println("链表为空!");
return;
}
if (this.head.getData() == data){
this.head = this.head.getNext();
return;
}
Node p = this.head;
while(null != p.getNext()){
if (p.getNext().getData() == data){
break;
}
p = p.getNext();
}
if (null != p.getNext()){
p.setNext(p.getNext().getNext());
print();
}else{
System.out.println(data + " 不存在!");
}
}
//输出链表元素
public void print(){
if (null == this.head){
return;
}
Node p = this.head;
while(null != p){
System.out.println(p.getData()+" ");
p = p.getNext();
}
}
//链表逆序
public void reverseLinkList() {
if (head == null || head.getNext() == null) {
return ;
} else {
Node temp = null;
Node p = head;
while (head != null) {
p = head.getNext();
head.setNext(temp);
temp = head;
head = p;
}
head = temp;
}
}
//判断是否为循环链表
public boolean isCircle(){
Node fast = head;
Node slow = head;
if (head == null || head.getNext() == null){
return false;
}
while(null != head){
fast = fast.getNext().getNext();
slow = slow.getNext();
if (fast == slow){
break;
}else if (fast == null || fast.getNext() == null){
return false;
}
}
return true;
}
双向链表:每个数据结点中都有两个指针,分别指向直接后继和直接前驱
双向链表的插入与删除操作
private Node head;
//头插法
public void headinsert (int data){
Node node = new Node(data,null,null);
if (null == this.head){
this.head = node;
return;
}
node.setNext(this.head);
this.head.setPrior(node);
this.head = node;
}
//尾插法
public void tailinsert(int data){
Node node = new Node(data,null,null);
if (null == this.head){
this.head = node;
return;
}
Node p = this.head;
while (null != p.getNext()){
p = p.getNext();
}
node.setPrior(p);
p.setNext(node);
}
//中间插入法
public void midinsert(int data){
Node node = new Node(data,null,null);
if (null == this.head){
this.head = node;
return;
}
if (this.head.getData() > data){
node.setNext(this.head);
this.head.setPrior(node);
this.head = node;
return;
}
Node p = this.head;
while (null != p.getNext()){
if (p.getNext().getData() > data ){
break;
}
p = p.getNext();
}
if (null == p.getNext()) {
node.setPrior(p);
p.setNext(node);
return;
}
node.setPrior(p);
node.setNext(p.getNext());
p.getNext().setPrior(node);
p.setNext(node);
}
//删除操作
public void remove(int data) {
if (null == this.head) {
System.out.println("链表为空!");
return;
}
if (this.head.getData() == data) {
this.head = this.head.getNext();
print();
return;
}
Node p = this.head;
while (null != p.getNext()) {
if (p.getNext().getData() == data) {
break;
}
p = p.getNext();
}
if (null == p.getNext()) {
System.out.println(data + " 不存在!");
} else {
p.setNext(p.getNext().getNext());
if (null != p.getNext()) {
p.getNext().setPrior(p);
}
print();
}
}
循环链表:将单链表中终端结点的指针端自空指针改为指向头结点,就使整个单链表形成一个环
循环链表的 插入与删除
Node head ;
Node tail ;
//头插法(可变参数)
public void headInsert(int... data){
if (null == data || 0 == data.length) {
return;
}
for (int d : data) {
Node node = new Node(d,null,null);
if (head == null){
head = node;
tail = node;
continue;
}
node.setNext(head);
head = node;
tail.setNext(head);
}
}
//尾插法(可变参数)
public void tailInsert(int... data) {
if (null == data || 0 == data.length) {
return;
}
for (int d : data) {
Node node = new Node(d, null, null);
if (head == null) {
head = node;
this.head.setNext(this.head);
tail = node;
continue;
}
Node p = this.head;
while (head != p.getNext()) {
p = p.getNext();
}
node.setPrior(p);
p.setNext(node);
tail.setNext(head);
}
}
//判断是否为循环链表
public boolean isCircle(){
Node fast = head;
Node slow = head;
if (head == null || head.getNext() == null){
return false;
}
while(null != head){
fast = fast.getNext().getNext();
slow = slow.getNext();
if (fast == slow){
break;
}else if (fast == null || fast.getNext() == null){
return false;
}
}
return true;
}
//删除节点
public void remove(int data){
if (null == this.head ){
System.out.println("链表为空!");
return;
}
if (this.head.getData() == data){
this.head = this.head.getNext();
this.tail.setNext(head);
return;
}
Node p = this.head;
while(head != p.getNext()){
if (p.getNext().getData() == data){
break;
}
p = p.getNext();
}
if (head != p.getNext()){
p.setNext(p.getNext().getNext());
}else{
System.out.println(data + " 不存在!");
}
}
3.栈
栈是后进先出的线性表(LIFO表),仅在表的一端进行插入和删除运算的线性表。通常称插入、删除的这一端为栈顶,另一端称为栈底。
用栈实现链表
private Node head;
private int size = 0;
//入栈
public void push (int data) {
Node node = new Node(data, null);
if (null == this.head) {
this.head = node;
size++;
return;
} else {
node.setNext(head);
head = node;
}
size++;
}
//出栈
public void pop(){
if (size == 0) {
System.out.println("队列为空!");
return;
}
Node temp = head;
head = head.getNext();
size--;
System.out.println(temp.getData());
}
//判断栈是否为空
public boolean isEmpty(){
if (head == null) {
return true;
}
return false;
}
4.队列
Queue是只允许在一端进行插入操作,而在另-端进行删除操作的先进先出线性表(FIFO)。允许插入的一端称为队尾,允许删除的一端称为队头。
循环队列
public class LoopQueue<T> {
private int DEFAULT_SIZE = 10;
private int capacity;//保存数组的长度
private Object[] elementData;//定义一个数组用于保存循环队列的元素
private int front = 0;//队头
private int rear = 0;//队尾
//以默认数组长度创建空循环队列
public LoopQueue() {
capacity = DEFAULT_SIZE;
elementData = new Object[capacity];
}
//以一个初始化元素来创建循环队列
public LoopQueue(T element) {
this();
elementData[0] = element;
rear++;
}
//以指定循环队列中第一个元素和指定长度的数组来创建循环队列
public LoopQueue(T element, int initSize) {
this.capacity = initSize;
elementData = new Object[capacity];
elementData[0] = element;
rear++;
}
//获取循环队列的大小
public int size() {
if (isEmpty()) {
return 0;
}
return rear > front ? rear - front : capacity - (front - rear);
}
//插入队列
public void add(T element) {
if (rear == front && elementData[front] != null) {
throw new IndexOutOfBoundsException("队列已满的异常");
}
elementData[rear++] = element;
//如果rear已经到头,那就转头
rear = rear == capacity ? 0 : rear;
}
//移除队列
public T remove() {
if (isEmpty()) {
throw new IndexOutOfBoundsException("空队列异常");
}
//保留队列的rear端的元素的值
T oldValue = (T) elementData[front];
//释放队列的front端的元素
elementData[front++] = null;
//如果front已经到头,那就转头
front = front == capacity ? 0 : front;
return oldValue;
}
//返回队列顶元素,但不删除队列顶元素
public T element() {
if (isEmpty()) {
throw new IndexOutOfBoundsException("空队列异常");
}
return (T) elementData[front];
}
//判断循环队列是否为空队列
public boolean isEmpty() {
//rear==front且rear处的元素为null
return rear == front && elementData[rear] == null;
}
//清空循环队列
public void clear() {
//将底层数组所有元素赋为null
Arrays.fill(elementData, null);
front = 0;
rear = 0;
}
public String toString() {
if (isEmpty()) {
return "[]";
} else {
//如果front < rear,有效元素就是front到rear之间的元素
if (front < rear) {
StringBuilder sb = new StringBuilder("[");
for (int i = front; i < rear; i++) {
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();
}
//如果front >= rear,有效元素为front->capacity之间、0->rear之间的
else {
StringBuilder sb = new StringBuilder("[");
for (int i = front; i < capacity; i++) {
sb.append(elementData[i].toString() + ", ");
}
for (int i = 0; i < rear; i++) {
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();
}
}
}
public static void main(String[] args) {
LoopQueue<String> queue = new LoopQueue<String>("aaaa", 3);
//添加两个元素
queue.add("bbbb");
queue.add("cccc");
//此时队列已满
System.out.println(queue);
//删除一个元素后,队列可以再多加一个元素
queue.remove();
System.out.println("删除一个元素后的队列:" + queue);
//再次添加一个元素,此时队列又满
queue.add("dddd");
System.out.println(queue);
System.out.println("队列满时的长度:" + queue.size());
}
}
本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文!