Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(三)

导读:本篇文章讲解 Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(三),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Java面试宝典之数据结构基础 —— 线性表篇

作者:egg

邮箱:xtfggef@gmail.com

微博:http://weibo.com/xtfggef

博客:http://blog.csdn.net/zhangerqing(转载请说明出处)

这部分内容作为计算机专业最基础的知识,几乎被所有企业选中用来作考题,因此,本章我们从本章开始,我们将从基础方面对数据结构进行讲解,内容主要是线性表,包括栈、队列、数组、字符串等,主要讲解基础知识,如概念及简单的实现代码,非线性结构我们在后面的文章中给出。过程中有任

何问题,请联系本人:http://weibo.com/xtfggef 

一、数据结构概念

用我的理解,数据结构包含数据和结构,通俗一点就是将数据按照一定的结构组合起来,不同的组合方式会有不同的效率,使用不同的场景,如此而已。比如我们最常用的数组,就是一种数据结构,有独特的承载数据的方式,按顺序排列,其特点就是你可以根据下标快速查找元素,但是因为在数组中插入和删除元素会有其它元素较大幅度的便宜,所以会带来较多的消耗,所以因为这种特点,使得数组适合:查询比较频繁,增、删比较少的情况,这就是数据结构的概念。数据结构包括两大类:线性结构和非线性结构,线性结构包括:数组、链表、队列、栈等,非线性结构包括树、图、表等及衍生类结构。本章我们先讲解线性结构,主要从数组、链表、队列、栈方面进行讨论,非线性数据结构在后面会继续讲解。

二、线性表

线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。其基本操作主要有:

   1)MakeEmpty(L) 这是一个将L变为空表的方法
   2)Length(L) 返回表L的长度,即表中元素个数 
   3)Get(L,i) 这是一个函数,函数值为L中位置i处的元素(1≤i≤n)
   4)Prev(L,i) 取i的前驱元素
   5)Next(L,i) 取i的后继元素
   6)Locate(L,x) 这是一个函数,函数值为元素x在L中的位置
   7)Insert(L,i,x)在表L的位置i处插入元素x,将原占据位置i的元素及后面的元素都向后推一个位置
   8)Delete(L,p) 从表L中删除位置p处的元素
   9)IsEmpty(L) 如果表L为空表(长度为0)则返回true,否则返回false
   10)Clear(L)清除所有元素
   11)Init(L)同第一个,初始化线性表为空
   12)Traverse(L)遍历输出所有元素
   13)Find(L,x)查找并返回元素
   14)Update(L,x)修改元素
   15)Sort(L)对所有元素重新按给定的条件排序
   16) strstr(string1,string2)用于字符数组的求string1中出现string2的首地址

不管采用哪种方式实现线性表,至少都应该具有上述这些基本方法,下面我会将下数据结构的基本实现方式。

三、基础数据结构

数据结构是一种抽象的数据类型(ADT),可以这么说,我们可以采用任意的方式实现某种数据结构,只要符合将要实现的数据结构的特点,数据结构就是一种标准,我们可以采用不同的方式去实现,最常用的两种就是数组和链表(包括单链表、双向链表等)。数组是非常常见的数据类型,在任何一种语言里都有它的实现,我们这里采用Java来简单实现一下数组。
数组是一种引用类型的对象,我们可以像下面这样的方式来声明数组:


   
  1. int a[];
  2. int[] b;
  3. int []c;

        a = new int[10];
   

总结起来,声明一个数组有基本的三个因素:类型、名称、下标,Java里,数组在格式上相对灵活,下标和名称可以互换位置,前三种情况我们可以理解为声明一个变量,后一种为其赋值。或者像下面这样,在声明的时候赋值:


   
  1. int c[] = { 2, 3, 6, 10, 99};
  2. int []d = new int[ 10];

我稍微解释一下,其实如果只执行:int[] b,只是在栈上创建一个引用变量,并未赋值,只有当执行d = new int[10]才会在堆上真正的分配空间。上述第一行为静态初始化,就是说用户指定数组的内容,有系统计算数组的大小,第二行恰恰相反,用户指定数组的大小,由系统分配初始值,我们打印一下数组的初始值:


   
  1. int []d = new int[ 10];
  2. System.out.println(d[ 2]);

结果输出0,对于int类型的数组,默认的初始值为0.

但是,绝对不可以像下面这样:

       int e[10] = new int[10];
   

无法通过编译,至于为什么,语法就是这样,这是一种规范,不用去想它。

我们可以通过下标来检索数组。下面我举个简单的例子,来说明下数组的用法。


   
  1. public static void main(String[] args) {
  2. String name[];
  3. name = new String[ 5];
  4. name[ 0] = "egg";
  5. name[ 1] = "erqing";
  6. name[ 2] = "baby";
  7. for ( int i = 0; i < name.length; i++) {
  8. System.out.println(name[i]);
  9. }
  10. }

这是最简单的数组声明、创建、赋值、遍历的例子,下面写个增删的例子。


   
  1. package com.xtfggef.algo.array;
  2. public class Array {
  3. public static void main(String[] args) {
  4. int value[] = new int[ 10];
  5. for ( int i = 0; i < 10; i++) {
  6. value[i] = i;
  7. }
  8. // traverse(value);
  9. // insert(value, 666, 5);
  10. delete(value, 3);
  11. traverse(value);
  12. }
  13. public static int[] insert( int[] old, int value, int index) {
  14. for ( int k = old.length - 1; k > index; k--)
  15. old[k] = old[k - 1];
  16. old[index] = value;
  17. return old;
  18. }
  19. public static void traverse(int data[]) {
  20. for ( int j = 0; j < data.length; j++)
  21. System.out.print(data[j] + " ");
  22. }
  23. public static int[] delete( int[] old, int index) {
  24. for ( int h = index; h < old.length - 1; h++) {
  25. old[h] = old[h + 1];
  26. }
  27. old[old.length - 1] = 0;
  28. return old;
  29. }
  30. }

简单写一下,主要想说明数组中删除和增加元素的原理:增加元素,需要将index后面的依次向后移动,然后将值插入index位置,删除则将后面的值依次向前移动,较简单。

要记住:数组是表示相同类型的一类数据的集合,下标从0开始,就行了。

数组实现的线下表可以参考ArrayList,在JDK中附有源码,感兴趣的同学可以读读。下面我简单介绍下单链表。

单链表是最简单的链表,有节点之间首尾连接而成,简单示意如下:

Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(三)

除了头节点,每个节点包含一个数据域一个指针域,除了头、尾节点,每个节点的指针指向下一个节点,下面我们写个例子操作一下单链表。


   
  1. package com.xtfggef.algo.linkedlist;
  2. public class LinkedList<T> {
  3. /**
  4. * class node
  5. * @author egg
  6. * @param <T>
  7. */
  8. private static class Node<T> {
  9. T data;
  10. Node<T> next;
  11. Node(T data, Node<T> next) {
  12. this.data = data;
  13. this.next = next;
  14. }
  15. Node(T data) {
  16. this(data, null);
  17. }
  18. }
  19. // data
  20. private Node<T> head, tail;
  21. public LinkedList() {
  22. head = tail = null;
  23. }
  24. /**
  25. * judge the list is empty
  26. */
  27. public boolean isEmpty() {
  28. return head == null;
  29. }
  30. /**
  31. * add head node
  32. */
  33. public void addHead(T item) {
  34. head = new Node<T>(item);
  35. if (tail == null)
  36. tail = head;
  37. }
  38. /**
  39. * add the tail pointer
  40. */
  41. public void addTail(T item) {
  42. if (!isEmpty()) {
  43. tail.next = new Node<T>(item);
  44. tail = tail.next;
  45. } else {
  46. head = tail = new Node<T>(item);
  47. }
  48. }
  49. /**
  50. * print the list
  51. */
  52. public void traverse() {
  53. if (isEmpty()) {
  54. System.out.println( "null");
  55. } else {
  56. for (Node<T> p = head; p != null; p = p.next)
  57. System.out.println(p.data);
  58. }
  59. }
  60. /**
  61. * insert node from head
  62. */
  63. public void addFromHead(T item) {
  64. Node<T> newNode = new Node<T>(item);
  65. newNode.next = head;
  66. head = newNode;
  67. }
  68. /**
  69. * insert node from tail
  70. */
  71. public void addFromTail(T item) {
  72. Node<T> newNode = new Node<T>(item);
  73. Node<T> p = head;
  74. while (p.next != null)
  75. p = p.next;
  76. p.next = newNode;
  77. newNode.next = null;
  78. }
  79. /**
  80. * delete node from head
  81. */
  82. public void removeFromHead() {
  83. if (!isEmpty())
  84. head = head.next;
  85. else
  86. System.out.println( "The list have been emptied!");
  87. }
  88. /**
  89. * delete frem tail, lower effect
  90. */
  91. public void removeFromTail() {
  92. Node<T> prev = null, curr = head;
  93. while (curr.next != null) {
  94. prev = curr;
  95. curr = curr.next;
  96. if (curr.next == null)
  97. prev.next = null;
  98. }
  99. }
  100. /**
  101. * insert a new node
  102. * @param appointedItem
  103. * @param item
  104. * @return
  105. */
  106. public boolean insert(T appointedItem, T item) {
  107. Node<T> prev = head, curr = head.next, newNode;
  108. newNode = new Node<T>(item);
  109. if (!isEmpty()) {
  110. while ((curr != null) && (!appointedItem.equals(curr.data))) {
  111. prev = curr;
  112. curr = curr.next;
  113. }
  114. newNode.next = curr;
  115. prev.next = newNode;
  116. return true;
  117. }
  118. return false;
  119. }
  120. public void remove(T item) {
  121. Node<T> curr = head, prev = null;
  122. boolean found = false;
  123. while (curr != null && !found) {
  124. if (item.equals(curr.data)) {
  125. if (prev == null)
  126. removeFromHead();
  127. else
  128. prev.next = curr.next;
  129. found = true;
  130. } else {
  131. prev = curr;
  132. curr = curr.next;
  133. }
  134. }
  135. }
  136. public int indexOf(T item) {
  137. int index = 0;
  138. Node<T> p;
  139. for (p = head; p != null; p = p.next) {
  140. if (item.equals(p.data))
  141. return index;
  142. index++;
  143. }
  144. return - 1;
  145. }
  146. /**
  147. * judge the list contains one data
  148. */
  149. public boolean contains(T item) {
  150. return indexOf(item) != - 1;
  151. }
  152. }

单链表最好玩儿的也就是增加和删除节点,下面的两个图分别是用图来表示单链表增、删节点示意,看着图学习,理解起来更加容易!

Java面试宝典系列之基础面试题String、变量、类与对象、集合类、SSH(三)

接下来的队列和栈,我们分别用不同的结构来实现,队列用数组,栈用单列表,读者朋友对此感兴趣,可以分别再用不同的方法实现。

四、队列
队列是一个常用的数据结构,是一种先进先出(First In First Out, FIFO)的结构,也就是说只能在表头进行删除,在表尾进行添加,下面我们实现一个简单的队列。


   
  1. package com.xtfggef.algo.queue;
  2. import java.util.Arrays;
  3. public class Queue<T> {
  4. private int DEFAULT_SIZE = 10;
  5. private int capacity;
  6. private Object[] elementData;
  7. private int front = 0;
  8. private int rear = 0;
  9. public Queue()
  10. {
  11. capacity = DEFAULT_SIZE;
  12. elementData = new Object[capacity];
  13. }
  14. public Queue(T element)
  15. {
  16. this();
  17. elementData[ 0] = element;
  18. rear++;
  19. }
  20. public Queue(T element , int initSize)
  21. {
  22. this.capacity = initSize;
  23. elementData = new Object[capacity];
  24. elementData[ 0] = element;
  25. rear++;
  26. }
  27. public int size()
  28. {
  29. return rear - front;
  30. }
  31. public void add(T element)
  32. {
  33. if (rear > capacity - 1)
  34. {
  35. throw new IndexOutOfBoundsException( "the queue is full!");
  36. }
  37. elementData[rear++] = element;
  38. }
  39. public T remove()
  40. {
  41. if (empty())
  42. {
  43. throw new IndexOutOfBoundsException( "queue is empty");
  44. }
  45. @SuppressWarnings( "unchecked")
  46. T oldValue = (T)elementData[front];
  47. elementData[front++] = null;
  48. return oldValue;
  49. }
  50. @SuppressWarnings( "unchecked")
  51. public T element()
  52. {
  53. if (empty())
  54. {
  55. throw new IndexOutOfBoundsException( "queue is empty");
  56. }
  57. return (T)elementData[front];
  58. }
  59. public boolean empty()
  60. {
  61. return rear == front;
  62. }
  63. public void clear()
  64. {
  65. Arrays.fill(elementData , null);
  66. front = 0;
  67. rear = 0;
  68. }
  69. public String toString()
  70. {
  71. if (empty())
  72. {
  73. return "[]";
  74. }
  75. else
  76. {
  77. StringBuilder sb = new StringBuilder( "[");
  78. for ( int i = front ; i < rear ; i++ )
  79. {
  80. sb.append(elementData[i].toString() + ", ");
  81. }
  82. int len = sb.length();
  83. return sb.delete(len - 2 , len).append( "]").toString();
  84. }
  85. }
  86. public static void main(String[] args){
  87. Queue<String> queue = new Queue<String>( "ABC", 20);
  88. queue.add( "DEF");
  89. queue.add( "egg");
  90. System.out.println(queue.empty());
  91. System.out.println(queue.size());
  92. System.out.println(queue.element());
  93. queue.clear();
  94. System.out.println(queue.empty());
  95. System.out.println(queue.size());
  96. }
  97. }

队列只能在表头进行删除,在表尾进行增加,这种结构的特点,适用于排队系统。

五、栈

栈是一种后进先出(Last In First Out,LIFO)的数据结构,我们采用单链表实现一个栈。


   
  1. package com.xtfggef.algo.stack;
  2. import com.xtfggef.algo.linkedlist.LinkedList;
  3. public class Stack<T> {
  4. static class Node<T> {
  5. T data;
  6. Node<T> next;
  7. Node(T data, Node<T> next) {
  8. this.data = data;
  9. this.next = next;
  10. }
  11. Node(T data) {
  12. this(data, null);
  13. }
  14. }
  15. @SuppressWarnings( "rawtypes")
  16. static LinkedList list = new LinkedList();
  17. @SuppressWarnings( "unchecked")
  18. public T push(T item) {
  19. list.addFromHead(item);
  20. return item;
  21. }
  22. public void pop() {
  23. list.removeFromHead();
  24. }
  25. public boolean empty() {
  26. return list.isEmpty();
  27. }
  28. public int search(T t) {
  29. return list.indexOf(t);
  30. }
  31. public static void main(String[] args) {
  32. Stack<String> stack = new Stack<String>();
  33. System.out.println(stack.empty());
  34. stack.push( "abc");
  35. stack.push( "def");
  36. stack.push( "egg");
  37. stack.pop();
  38. System.out.println(stack.search( "def"));
  39. }
  40. }

本章的内容都是很基础的,重在让读者朋友们理解数据结构的概念,下章开始,我们会介绍树、二叉树等Java中的实现,敬请读者朋友们持续关注!

作者:egg

邮箱:xtfggef@gmail.com

微博:http://weibo.com/xtfggef

博客:http://blog.csdn.net/zhangerqing(转载请说明出处)

有问题,请依照上述联系方式联系作者,欢迎读者及时提出建议,谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72764.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!