数据结构~05.双链表的操作,手写Java语言中的LinkedList集合

爱被打了一巴掌 2023-02-28 08:45 58阅读 0赞

数据结构~05.双链表的操作,手写LinkedList集合

本文是上一篇文章的后续,详情点击该链接~

先写一个普通的双链表插入和遍历~

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct no_de {
  4. int data; //data中存放数据域
  5. struct no_de* pre; //指向前驱结点的指针
  6. struct no_de* next; //指向后继结点的指针
  7. }Node;
  8. //建立头节点
  9. Node* getHead() {
  10. Node* head = (Node*)malloc(sizeof(Node));
  11. head->data = NULL;
  12. head->next = NULL;
  13. head->pre = NULL;
  14. return head;
  15. }
  16. //插入操作
  17. void Insert(Node *L,int data) {
  18. Node* p = (Node*)malloc(sizeof(Node));
  19. p->data = data;
  20. p->next = L->next;
  21. p->pre = L;
  22. L->next = p;
  23. }
  24. //遍历链表
  25. void Print(Node *L) {
  26. Node* p = L->next;
  27. //如果链表为空就输出[]
  28. if (p == NULL) {
  29. printf("[]");
  30. }
  31. //遍历链表
  32. while (p != NULL) {
  33. //判断是否到了最后
  34. if (p ->next != NULL) {
  35. printf("%d->",p->data);
  36. }
  37. else {
  38. printf("%d",p->data);
  39. }
  40. p = p->next;
  41. }
  42. }
  43. int main(int argc,char * argv[]) {
  44. Node* list = getHead();
  45. Insert(list,1); Insert(list, 2); Insert(list, 3); Insert(list, 4);
  46. Print(list);
  47. getchar();
  48. return 0;
  49. }

删除结点的算法

  1. //在单链表的基础上做了稍稍修改~
  2. q = p->next;
  3. p->next = q->next;
  4. q->next->pre = p;
  5. free(q);

查找结点的算法

  1. Node* findNode(Node *C, int x) {
  2. Node* p = C->next;
  3. while (p != NULL) {
  4. if (p ->data == x) {
  5. break;
  6. }
  7. p = p->next;
  8. }
  9. return p;
  10. }

奉上完整代码

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct no_de {
  4. int data; //data中存放数据域
  5. struct no_de* pre; //指向前驱结点的指针
  6. struct no_de* next; //指向后继结点的指针
  7. }Node;
  8. //建立头节点
  9. Node* getHead() {
  10. Node* head = (Node*)malloc(sizeof(Node));
  11. head->data = NULL;
  12. head->next = NULL;
  13. head->pre = NULL;
  14. return head;
  15. }
  16. //插入操作
  17. void Insert(Node *L,int data) {
  18. Node* p = (Node*)malloc(sizeof(Node));
  19. p->data = data;
  20. p->next = L->next;
  21. p->pre = L;
  22. L->next = p;
  23. }
  24. //删除操作
  25. int Delete(Node* C, int s) {
  26. Node* p, * q;
  27. p = C;
  28. //开始查找
  29. while (p->next != NULL) {
  30. if (p->next->data == s) {
  31. break;
  32. }
  33. p = p->next;
  34. }
  35. if (p->next == NULL) {
  36. return 0;
  37. }
  38. else {
  39. //开始删除
  40. q = p->next;
  41. p->next = q->next;
  42. q->next->pre = p;
  43. free(q);
  44. return 1;
  45. }
  46. }
  47. //遍历链表
  48. void Print(Node *L) {
  49. Node* p = L->next;
  50. //如果链表为空就输出[]
  51. if (p == NULL) {
  52. printf("[]");
  53. }
  54. //遍历链表
  55. while (p != NULL) {
  56. //判断是否到了最后
  57. if (p ->next != NULL) {
  58. printf("%d->",p->data);
  59. }
  60. else {
  61. printf("%d",p->data);
  62. }
  63. p = p->next;
  64. }
  65. printf("\n");
  66. }
  67. //查找结点
  68. Node* findNode(Node *C, int x) {
  69. Node* p = C->next;
  70. while (p != NULL) {
  71. if (p ->data == x) {
  72. break;
  73. }
  74. p = p->next;
  75. }
  76. return p;
  77. }
  78. int main(int argc,char * argv[]) {
  79. Node* list = getHead();
  80. Insert(list,1); Insert(list, 2); Insert(list, 3); Insert(list, 4);
  81. Delete(list,2);
  82. Print(list);
  83. Node* p = findNode(list,3);
  84. printf("%d",p->data);
  85. getchar();
  86. return 0;
  87. }

采用尾插法建立双链表?

  1. void InsertLast(Node*& L, int a[], int n) {
  2. Node* s, * r;
  3. int i;
  4. L = (Node*)malloc(sizeof(Node));
  5. L->pre = NULL;
  6. L->next = NULL;
  7. //这里和单链表一样, r始终指向终端结点
  8. r = L;
  9. for (i = 0; i < n; ++i) {
  10. //建立新结点
  11. s = (Node*)malloc(sizeof(Node));
  12. s->data = a[i];
  13. //将s 插入到 L的尾部,并且r 指向 s
  14. r->next = s;
  15. s->pre = r;
  16. r = s;
  17. }
  18. r->next = NULL;
  19. }

Java中的LinkedList

定义List接口

  1. public interface List <E>{
  2. int size();
  3. boolean isEmpty();
  4. boolean contains(E element);
  5. void add(E element);
  6. E get(int index);
  7. E set(int index,E element);
  8. void add(int index,E element);
  9. E remove(int index);
  10. int indexOf(E element);
  11. void clear();
  12. String toString();
  13. }

接口实现

  1. public class LinkedList<E> implements List<E>{
  2. private int size; //集合的长度
  3. private Node first;
  4. private Node last;
  5. @Override
  6. public int size() {
  7. return size;
  8. }
  9. //判断当前集合中是否有元素
  10. @Override
  11. public boolean isEmpty() {
  12. return size == 0;
  13. }
  14. //判断当前元素是否存在
  15. @Override
  16. public boolean contains(E element) {
  17. return indexOf(element) > -1;
  18. }
  19. @Override
  20. public void add(E element) {
  21. //调用下面的add方法,根据size保证每次都添加在最后
  22. add(size,element);
  23. }
  24. //取得坐标位置上的节点
  25. private Node<E> node(int index){
  26. Node N = first; //指向头
  27. //先判断要查找的index,是靠近头还是靠近尾
  28. //如果靠近头就从头开始查找,如果靠近尾就从尾开始查找
  29. //方法: 根据index 和 size的一半去比较
  30. if(index > (size >> 1)){
  31. //靠近尾
  32. N = last; //指向尾
  33. for(int i = size-1; i > index; i--){
  34. N = N.pre;
  35. }
  36. }else{
  37. //靠近头
  38. for(int i = 0; i < index; i++){
  39. N = N.next;
  40. }
  41. }
  42. return N;
  43. }
  44. @Override
  45. public E get(int index) {
  46. //防止坐标越界
  47. if(index < 0 || index >= size){
  48. throw new IndexOutOfBoundsException("index: " + index + " size: " + size);
  49. }
  50. //调用方法
  51. return node(index).element;
  52. }
  53. @Override
  54. public E set(int index, E element) {
  55. //获得index上的node
  56. Node<E> node = node(index);
  57. //保存原来的值
  58. E oldElement = node.element;
  59. //新值覆盖老值
  60. node.element = element;
  61. //返回老值
  62. return oldElement;
  63. }
  64. @Override
  65. public void add(int index, E element) {
  66. //当需要添加到末尾时
  67. if(index == size) {
  68. //拿到last节点
  69. Node l = last;
  70. //构建node 完成指向关系
  71. Node newNode = new Node(l,null,element);
  72. //将原来的last 节点的next 修改成新构建出来的node
  73. last = newNode;
  74. if(l == null){
  75. first = newNode;
  76. }else {
  77. l.next = newNode;
  78. }
  79. }else{
  80. //获得指定的index
  81. Node<E> node = node(index);
  82. //获得前一个结点
  83. Node<E> pre = node.pre;
  84. //构建新的now 完成指向关系
  85. Node<E> newNode = new Node(pre, node, element);
  86. //改变指向
  87. pre.next = newNode;
  88. if (pre == null) {
  89. first = newNode;
  90. } else {
  91. node.pre = newNode;
  92. }
  93. }
  94. size++;
  95. }
  96. //链表删除的主要原理就是将被删除者的前一个元素指向后一个元素
  97. //比如 A->B->C 当我要删除B的时候,就让A -> C
  98. @Override
  99. public E remove(int index) {
  100. //防止坐标越界
  101. if(index < 0 || index >= size){
  102. throw new IndexOutOfBoundsException("index: " + index + " size: " + size);
  103. }
  104. //获得要删除的元素Node
  105. Node<E>node = node(index);
  106. //获得前一个结点
  107. Node<E> pre = node.pre;
  108. //获得后一个结点
  109. Node<E> next = node.next;
  110. if(pre == null){
  111. //firest进行修改
  112. first = next;
  113. next.pre = null;
  114. }else{
  115. //改变前一个结点的next
  116. pre.next = next;
  117. }
  118. if(next == null){
  119. //last进行修改
  120. last = pre;
  121. }else{
  122. next.pre = pre;
  123. }
  124. size--;
  125. //返回老元素
  126. return node.element;
  127. }
  128. @Override
  129. public int indexOf(E element) {
  130. //查找element元素是否存在,有返回索引,没有返回-1
  131. Node N = first;
  132. int index = 0;
  133. //遍历
  134. for(Node i = N; i != null; i = i.next){
  135. if(element == i.element){
  136. return index;
  137. }
  138. index++;
  139. }
  140. return -1;
  141. }
  142. @Override
  143. public void clear() {
  144. size = 0;
  145. first = null;
  146. last = null;
  147. }
  148. public String toString(){
  149. Node N = first;
  150. StringBuilder stringBuilder = new StringBuilder("[");
  151. boolean flag = false; //判断是否循环到了最后
  152. for(Node i = N; i != null; i = i.next){
  153. //说明已经到了最后一个元素
  154. if(i.next == null) {
  155. flag = true;
  156. }
  157. //如果没到最后就加 逗号
  158. if(flag == false){
  159. stringBuilder.append(i.element + ",");
  160. }else{ //到了最后就不加逗号
  161. stringBuilder.append(i.element);
  162. }
  163. }
  164. stringBuilder.append("]");
  165. return stringBuilder.toString();
  166. }
  167. //内部Node节点类
  168. private static class Node<E>{
  169. Node<E> pre;
  170. Node<E> next;
  171. E element;
  172. public Node(Node next,E element){
  173. this.next = next;
  174. this.element = element;
  175. }
  176. public Node(Node pre,Node next,E element){
  177. this.pre = pre;
  178. this.next = next;
  179. this.element = element;
  180. }
  181. public Node() {
  182. }
  183. }
  184. }

发表评论

表情:
评论列表 (有 0 条评论,58人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java操作

    Java中双链表的操作 1. 双链表根据内容添加结点 2. 双链表根据内容删除结点 3. 双链表根据内容修改(新内容替换旧内容) 4. 双链表根据内容查找结点索引