• 线性数据—栈、队列、链表


    一、栈 Stack(存取O(1))

    先进后出,进去123,出来321。
    基于数组:最后一位为栈尾,用于取操作。
    基于链表:第一位为栈尾,用于取操作。

    1.1、数组栈 

    1. /**
    2. * 基于数组实现的顺序栈; items[0]:表头/栈底; items[size-1]:表尾/栈顶;
    3. */
    4. public class MyArrayStack {
    5. // 存储元素的 数组
    6. private String items[];
    7. // 栈实际大小
    8. private int size =0;
    9. // 栈的容量
    10. private int capacity = 0;
    11. public MyArrayStack(int capacity) {
    12. this.size = 0;
    13. this.capacity = capacity;
    14. this.items = new String[capacity];
    15. }
    16. /**
    17. * 入栈
    18. */
    19. public boolean push(String item) {
    20. if(size >= capacity){
    21. throw new IndexOutOfBoundsException("MyArrayStack 栈的内存满了");
    22. }
    23. items[size] = item;
    24. size++;
    25. return true;
    26. }
    27. /**
    28. * 出栈
    29. */
    30. public String pop() {
    31. if(size<=0){
    32. throw new IndexOutOfBoundsException("MyArrayStack 栈的内存空了");
    33. }
    34. String item = items[size-1];
    35. items[size-1] = null;
    36. size--;
    37. return item;
    38. }
    39. }

    1.2、链表栈 

    1. /**
    2. * 基于链表实现的链式栈 top: 表尾/栈顶;
    3. */
    4. public class MyLinkedStack {
    5. // 表尾/栈顶;
    6. private Node top = null;
    7. /**
    8. * 入栈
    9. */
    10. public void push(String value) {
    11. Node node = new Node(value,null);
    12. if(top != null){
    13. node.nextNode = top;
    14. }
    15. top = node;
    16. }
    17. /**
    18. * 出栈
    19. */
    20. public String pop() {
    21. if(top==null){
    22. throw new IndexOutOfBoundsException("MyLinkedStack 栈的内存空了");
    23. }
    24. String retValue = top.getValue();
    25. top = top.nextNode;
    26. return retValue;
    27. }
    28. /**
    29. * 节点
    30. */
    31. private static class Node{
    32. // 存储数据
    33. private String value;
    34. // 下个节点
    35. private Node nextNode;
    36. public Node(String value, Node nextNode) {
    37. this.value = value;
    38. this.nextNode = nextNode;
    39. }
    40. public String getValue() {
    41. return value;
    42. }
    43. }
    44. }

    二、队列 Queue (存取O(1))

    先进先出(FIFO)的有序列表 

    2.1、数组单向队列 (存取O(1))

    1. /**
    2. * 基于数组实现的顺序队列
    3. */
    4. public class MyArrayQueue {
    5. private String [] items;
    6. // 容量
    7. private int capacity = 0;
    8. // 队头下标
    9. private int head = 0;
    10. // 队尾下标
    11. private int tail = 0;
    12. public MyArrayQueue(int capacity) {
    13. this.items = new String [capacity];
    14. this.capacity = capacity;
    15. }
    16. /**
    17. * 入队
    18. */
    19. public boolean enqueue(String item) {
    20. if(capacity == tail){
    21. throw new IndexOutOfBoundsException("MyArrayQueue 容量满了");
    22. }
    23. items[tail] = item;
    24. tail++;
    25. return true;
    26. }
    27. /**
    28. * 出队
    29. */
    30. public String dequeue() {
    31. if(head==tail){
    32. throw new IndexOutOfBoundsException("MyArrayQueue 容量空了");
    33. }
    34. String retValue = items[head];
    35. head++;
    36. return retValue;
    37. }
    38. }

    2.2、链表单向队列 

    1. /**
    2. * 基于链表实现的链式队列
    3. */
    4. public class MyLinkedListQueue {
    5. // 队头
    6. private Node head = null;
    7. // 队尾
    8. private Node tail = null;
    9. /**
    10. * 入队
    11. */
    12. public void enqueue(String value) {
    13. Node node = new Node(value,null);
    14. if(tail==null){
    15. head = node;
    16. tail = node;
    17. }else {
    18. tail.next=node;
    19. tail=node;
    20. }
    21. }
    22. /**
    23. * 出队
    24. */
    25. public String dequeue() {
    26. if(head==null){
    27. throw new IndexOutOfBoundsException("MyLinkedListQueue 队列空了");
    28. }
    29. String retValue = head.getValue();
    30. head = head.next;
    31. if (head == null) {
    32. tail = null;
    33. }
    34. return retValue;
    35. }
    36. private static class Node{
    37. private String value;
    38. private Node next;
    39. public Node(String value, Node next) {
    40. this.value = value;
    41. this.next = next;
    42. }
    43. public String getValue() {
    44. return value;
    45. }
    46. }
    47. }

    三、链表 LinkedList 

    3.1、单向链表 

    1. /**
    2. * 单向普通链表
    3. */
    4. public class MyLinkedList {
    5. // 链表大小
    6. private int size;
    7. // 表头
    8. private Node head;
    9. /**
    10. * 插入
    11. */
    12. public void insert(int index, String value) {
    13. if(index<0){
    14. throw new IndexOutOfBoundsException("MyLinkedList 下标越界了");
    15. } else {
    16. if(head==null){
    17. head = new Node(value,null);
    18. }else {
    19. if(index>=size){
    20. index = size-1;
    21. }
    22. Node prev = head;
    23. for(int i=0;i
    24. prev = prev.next;
    25. }
    26. Node node = new Node(value,prev);
    27. prev.next =node;
    28. }
    29. size++;
    30. }
    31. }
    32. /**
    33. * 获取
    34. */
    35. public String get(int index){
    36. if(size<=0){
    37. throw new IllegalArgumentException("MyLinkedList 空链表");
    38. }
    39. if(index<0 || index>=size) {
    40. throw new IllegalArgumentException("MyLinkedList 下标越界了");
    41. }
    42. Node prev = head;
    43. for (int i=0;i
    44. prev = prev.next;
    45. }
    46. return prev.getValue();
    47. }
    48. private class Node{
    49. private String value;
    50. private Node next;
    51. public Node(String value, Node next) {
    52. this.value = value;
    53. this.next = next;
    54. }
    55. public String getValue() {
    56. return value;
    57. }
    58. }
    59. }

    3.2、双向链表 

    1. public class MyDoubleLinkedList {
    2. // 链表大小
    3. private int size;
    4. // 表头
    5. private Node head;
    6. // 表尾
    7. private Node tail;
    8. /**
    9. * 插入
    10. */
    11. public void insert(int index,String data) {
    12. if(index < 0) {
    13. throw new IndexOutOfBoundsException("MyDoubleLinkedList insert 下标越界");
    14. }
    15. Node node = new Node(data,null,null);
    16. if(index == 0) {
    17. head.next = node.next;
    18. head= node;
    19. return;
    20. }
    21. if(index >= size) {
    22. tail.prev = node.prev;
    23. tail= node;
    24. return;
    25. }
    26. Node cur = this.head;
    27. while(index != 0) {
    28. cur = cur.next;
    29. index--;
    30. }
    31. node.next = cur;
    32. cur.prev.next = node;
    33. node.prev = cur.prev;
    34. cur.prev = node;
    35. }
    36. public String get(int index){
    37. if(index<0||index>size){
    38. throw new IndexOutOfBoundsException("MyDoubleLinkedList get 下标越界了");
    39. }
    40. if(index<=(size/2)){
    41. Node cur = head;
    42. for(int i = 0;i1;i++){
    43. cur = head.next;
    44. }
    45. return cur.getValue();
    46. }else {
    47. index = size-index;
    48. Node cur = tail;
    49. for (int i=size;i>index;i--){
    50. cur = cur.prev;
    51. }
    52. return cur.getValue();
    53. }
    54. }
    55. private class Node{
    56. public String value;
    57. public Node prev;
    58. public Node next;
    59. public Node(String value, Node prev, Node next) {
    60. this.value = value;
    61. this.prev = prev;
    62. this.next = next;
    63. }
    64. public String getValue() {
    65. return value;
    66. }
    67. }
    68. }

    3.3、跳表 

    1.跳表由很多层结构组成,level是通过一定的概率随机产生的;
    2.每一层都是一个有序的链表,默认是升序 ;
    3.最底层(Level 1)的链表包含所有元素;
    4.如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现;
    5.每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

    1. import java.util.Random;
    2. public class SkipList {
    3. // 跳表中存储的是正整数,并且存储的数据是不重复的
    4. private static final int MAX_LEVEL = 16;
    5. // 结点的个数
    6. private int levelCount = 1;
    7. // 索引的层级数
    8. private final Node head = new Node();
    9. // 头结点
    10. private final Random random = new Random();
    11. // 查找操作
    12. public Node find(int value) {
    13. Node p = head;
    14. for (int i = levelCount - 1; i >= 0; --i) {
    15. while (p.next[i] != null && p.next[i].data < value) {
    16. p = p.next[i];
    17. }
    18. }
    19. if (p.next[0] != null && p.next[0].data == value) {
    20. return p.next[0]; // 找到,则返回原始链表中的结点
    21. } else {
    22. return null;
    23. }
    24. }
    25. // 插入操作
    26. public void insert(int value) {
    27. int level = randomLevel();
    28. Node newNode = new Node();
    29. newNode.data = value;
    30. newNode.maxLevel = level; // 通过随机函数改变索引层的结点布置
    31. Node[] update = new Node[level];
    32. for (int i = 0; i < level; ++i) {
    33. update[i] = head;
    34. }
    35. Node p = head;
    36. for (int i = level - 1; i >= 0; --i) {
    37. while (p.next[i] != null && p.next[i].data < value) {
    38. p = p.next[i];
    39. }
    40. update[i] = p;
    41. }
    42. for (int i = 0; i < level; ++i) {
    43. newNode.next[i] = update[i].next[i];
    44. update[i].next[i] = newNode;
    45. }
    46. if (levelCount < level) {
    47. levelCount = level;
    48. }
    49. }
    50. // 删除操作
    51. public void delete(int value) {
    52. Node[] update = new Node[levelCount];
    53. Node p = head;
    54. for (int i = levelCount - 1; i >= 0; --i) {
    55. while (p.next[i] != null && p.next[i].data < value) {
    56. p = p.next[i];
    57. }
    58. update[i] = p;
    59. }
    60. if (p.next[0] != null && p.next[0].data == value) {
    61. for (int i = levelCount - 1; i >= 0; --i) {
    62. if (update[i].next[i] != null && update[i].next[i].data == value) {
    63. update[i].next[i] = update[i].next[i].next[i];
    64. }
    65. }
    66. }
    67. }
    68. // 随机函数
    69. private int randomLevel() {
    70. int level = 1;
    71. for (int i = 1; i < MAX_LEVEL; ++i) {
    72. if (random.nextInt() % 2 == 1) {
    73. level++;
    74. }
    75. }
    76. return level;
    77. }
    78. // Node内部类
    79. public static class Node {
    80. private int data = -1;
    81. private final Node[] next = new Node[MAX_LEVEL];
    82. private int maxLevel = 0;
    83. // 重写toString方法
    84. @Override
    85. public String toString() {
    86. return "{data:" +
    87. data +
    88. "; levels: " +
    89. maxLevel +
    90. " }";
    91. }
    92. }
    93. // 显示跳表中的结点
    94. public void display() {
    95. Node p = head;
    96. while (p.next[0] != null) {
    97. System.out.println(p.next[0] + " ");
    98. p = p.next[0];
    99. }
    100. System.out.println();
    101. }
    102. }

  • 相关阅读:
    使用vite搭建vue3
    xxis not in the sudoers file. This incident will be reported.
    【国科大——矩阵分析与应用】使用高斯消元法,测试二元一次方程系数产生的误差
    部署Docker玩转Docker
    一文读懂Layer 2:Layer 2指基于底层区块链...
    Nginx入门到搭建
    Python脚本打包
    设计模式之策略模式
    VS2022ide下使用C++实现简谐振动,C语言程序设计简谐运动的模拟,C语言课程设计简谐振动实验的模拟。
    Tungsten Fabric数据量过大问题处理初探
  • 原文地址:https://blog.csdn.net/weixin_42679286/article/details/133296952