Java如何使用头插法,将一个数组有序插入一个已经排序之后的双向链表中合适的位置的呢?代码的思想会是什么呢?解释一下
效果如图:
代码
class Node {
int val;
Node prev;
Node next;
public Node(int val) {
this.val = val;
}
}
public class Main {
public static Node insertArrayToLinkedList(int[] arr, Node head) {
for (int i = 0; i < arr.length; i++) {
Node newNode = new Node(arr[i]);
if (head == null) { // 链表为空,直接将新节点作为头节点
head = newNode;
continue;
}
Node current = head;
boolean inserted = false;
while (current != null) {
if (arr[i] <= current.val) {
if (current == head) { // 要插入的位置是链表头部
newNode.next = current;
current.prev = newNode;
head = newNode;
} else { // 要插入的位置在链表中间
newNode.next = current;
newNode.prev = current.prev;
current.prev.next = newNode;
current.prev = newNode;
}
inserted = true;
break;
}
current = current.next;
}
if (!inserted) { // 要插入的位置在链表末尾
Node tail = head;
while (tail.next != null) {
tail = tail.next;
}
tail.next = newNode;
newNode.prev = tail;
}
}
return head;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9};
Node head = null;
head = insertArrayToLinkedList(arr, head);
// 输出链表的值,验证插入结果
Node current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
}
}
思路分析:
①遍历给定的数组,对于每个元素执行以下步骤
②为当前数组元素创建一个新的链表节点
③从链表的头部开始逐个比较链表节点的值和当前数组元素的值,找到第一个大于等于当前元素值的节点位置。如果找到了插入位置,则跳至④步骤,如果未找到插入位置,则当前元素的值大于链表中的所有节点值,需要将新节点插入到链表末尾
④将新节点插入到找到的插入位置之前。需要更新新节点的前驱指针和后继指针,以及前一个节点和后一个节点的指针。
⑤重复上述步骤:继续遍历数组中的下一个元素,重复执行步骤 ② 到步骤④
⑥遍历数组完成后,返回链表的头节点就ok了
头插法是一种将元素插入链表头部的插入方法。要将一个数组有序插入一个已经排序之后的双向链表中合适的位置,可以使用以下步骤和思路:
这种方法的思想是通过遍历链表,找到新节点应该插入的位置,并进行插入操作。由于链表已经是有序的,所以可以通过比较节点的值确定插入的位置,以保持链表的有序性。
以下是一个示例代码实现:
class Node {
int data;
Node prev;
Node next;
public Node(int data) {
this.data = data;
}
}
public class InsertSortedArrayToList {
public static Node insertSortedArrayToList(int[] array) {
Node head = new Node(Integer.MIN_VALUE);
Node current = head;
for (int i = 0; i < array.length; i++) {
Node newNode = new Node(array[i]);
while (current.next != null && current.next.data < newNode.data) {
current = current.next;
}
newNode.next = current.next;
if (current.next != null) {
current.next.prev = newNode;
}
newNode.prev = current;
current.next = newNode;
}
return head.next;
}
public static void main(String[] args) {
int[] array = {2, 4, 6, 8};
Node result = insertSortedArrayToList(array);
// 遍历链表并打印节点的值
Node current = result;
while (current != null) {
System.out.print(current.data + " ");
current = current.next;
}
}
}
在上述代码中,我们使用头插法将有序数组 {2, 4, 6, 8}
插入一个已排序的双向链表中(假设双向链表里面有值)。
1. 图类型:
package com.usts.edu.graphic;
// 图的种类 有向图、有向网、无向图、无向网
public enum GraphKind {
UDG, // 无向图(UnDirected Graph)
DG, // 有向图(Directed Graph)
UDN, // 无向网(UnDirected Network)
DN; // 有向网(Directed Network)
}
2. 图的接口
package com.usts.edu.graphic;
//图的接口
public interface IGraph {
void createGraph();//创建一个图
int getVexNum(); // 返回顶点数
int getArcNum();// 返回边数
Object getVex(int v) throws Exception;// 返回v表示结点的值, 0 <= v < vexNum
int locateVex(Object vex);// 给定顶点的值vex,返回其在图中的位置,如果图中不包含此顶点,则返回-1
int firstAdjVex(int v) throws Exception; // 返回v的第一个邻接点,若v没有邻接点,则返回-1,其中0≤v<vexNum
int nextAdjVex(int v, int w) throws Exception;// 返回v相对于w的下一个邻接点,若w是v的最后一个邻接点,则返回-1,其中0≤v, w<vexNum
}
3. 创建图:
package com.usts.edu.graphic;
import java.util.Scanner;
public class MGraph implements IGraph {
public final static int INFINITY = Integer.MAX_VALUE;
private GraphKind kind;
private int vexNum, arcNum;
private Object[] vexs;
private int[][] arcs;
public MGraph() {
this(null, 0, 0, null, null);
}
public MGraph(GraphKind kind, int vexNum, int arcNum, Object[] vexs,
int[][] arcs) {
this.kind = kind;
this.vexNum = vexNum;
this.arcNum = arcNum;
this.vexs = vexs;
this.arcs = arcs;
}
public void createGraph() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入图的类型");
GraphKind kind = GraphKind.valueOf(sc.next());
switch (kind) {
case UDG:
createUDG();
return;
case DG:
createDG();
return;
case UDN:
createUDN();
return;
case DN:
createDN();
return;
}
}
private void createUDG() {
};
private void createDG() {
};
private void createUDN() {
Scanner sc = new Scanner(System.in);
vexNum = sc.nextInt();
arcNum = sc.nextInt();
vexs = new Object[vexNum];
for (int v = 0; v < vexNum; v++)
vexs[v] = sc.next();
arcs = new int[vexNum][vexNum];
for (int v = 0; v < vexNum; v++)
for (int u = 0; u < vexNum; u++)
arcs[v][u] = INFINITY;
for (int k = 0; k < arcNum; k++) {
int v = locateVex(sc.next());
int u = locateVex(sc.next());
arcs[v][u] = arcs[u][v] = sc.nextInt();
}
}
private void createDN() {
Scanner sc = new Scanner(System.in);
vexNum = sc.nextInt();
arcNum = sc.nextInt();
vexs = new Object[vexNum];
for (int v = 0; v < vexNum; v++)
vexs[v] = sc.next();
arcs = new int[vexNum][vexNum];
for (int v = 0; v < vexNum; v++)
for (int u = 0; u < vexNum; u++)
arcs[v][u] = INFINITY;
for (int k = 0; k < arcNum; k++) {
int v = locateVex(sc.next());
int u = locateVex(sc.next());
arcs[v][u] = sc.nextInt();
}
}
public int getVexNum() {
return vexNum;
}
public int getArcNum() {
return arcNum;
}
public int locateVex(Object vex) {
for (int v = 0; v < vexNum; v++)
if (vexs[v].equals(vex))
return v;
return -1;
}
public Object getVex(int v) throws Exception {
if (v < 0 && v >= vexNum)
throw new Exception("第" + v + "个顶点不存在!");
return vexs[v];
}
public int firstAdjVex(int v) throws Exception {
if (v < 0 && v >= vexNum)
throw new Exception("第" + v + "个顶点不存在!");
for (int j = 0; j < vexNum; j++)
if (arcs[v][j] != 0 && arcs[v][j] < INFINITY)
return j;
return -1;
}
public int nextAdjVex(int v, int w) throws Exception {
if (v < 0 && v >= vexNum)
throw new Exception("第" + v + "个顶点不存在!");
for (int j = w + 1; j < vexNum; j++)
if (arcs[v][j] != 0 && arcs[v][j] < INFINITY)
return j;
return -1;
}
public GraphKind getKind() {
return kind;
}
public int[][] getArcs() {
return arcs;
}
public Object[] getVexs() {
return vexs;
}
public void setArcNum(int arcNum) {
this.arcNum = arcNum;
}
public void setArcs(int[][] arcs) {
this.arcs = arcs;
}
public void setKind(GraphKind kind) {
this.kind = kind;
}
public void setVexNum(int vexNum) {
this.vexNum = vexNum;
}
public void setVexs(Object[] vexs) {
this.vexs = vexs;
}
}
4. 实现搜索:
package com.usts.edu.graphic;
import com.usts.edu.Queue.LinkQueue;
/**
* Created by Guanzhong Hu
* Date :2020/3/30
* Description :
* Version :1.0
*/
public class GDSeach {
public final static int INFINITY = Integer.MAX_VALUE;
public static void CC_BFS(IGraph G) throws Exception {
boolean[] visited = new boolean[G.getVexNum()];
for (int v = 0; v < G.getVexNum(); v++)
visited[v] = false;
LinkQueue Q = new LinkQueue();
LinkQueue P = new LinkQueue();
int i = 0;
for (int v = 0; v < G.getVexNum(); v++) {
P.clear();
if (!visited[v]) {
visited[v] = true;
P.offer(G.getVex(v));
Q.offer(v);
while (!Q.isEmpty()) {
int u = (Integer) Q.poll();
for (int w = G.firstAdjVex(u); w >= 0; w = G.nextAdjVex(u,
w)) {
if (!visited[w]) {
visited[w] = true;
P.offer(G.getVex(w));
Q.offer(w);
}
}
}
System.out.println("图的第" + ++i + "个连通分量为:");
while (!P.isEmpty())
System.out.print(P.poll().toString() + " ");
System.out.println();
}
}
}
public static void main(String[] args) throws Exception {
Object vexs[] = { "A", "B", "C", "D", "E", "F", "G" };
int[][] arcs = { { 0, 1, INFINITY, 1, INFINITY, INFINITY, INFINITY },
{ 1, 0, 1, INFINITY, INFINITY, INFINITY, INFINITY },
{ INFINITY, 1, 0, 1, INFINITY, INFINITY, INFINITY },
{ 1, INFINITY, 1, 0, INFINITY, INFINITY, INFINITY },
{ INFINITY, INFINITY, INFINITY, INFINITY, 0, 1, INFINITY },
{ INFINITY, INFINITY, INFINITY, INFINITY, 1, 0, 1 },
{ INFINITY, INFINITY, INFINITY, INFINITY, INFINITY, 1, 0 }, };
MGraph G = new MGraph(GraphKind.UDG, 7, 6, vexs, arcs);
CC_BFS(G);
}
}
无向图的连通分量搜索是一种广度优先遍历的应用,当然还有如Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。
源码地址:
https://gitee.com/jockhome/data_structure在给定的代码中,我们使用了头插法来将一个有序数组插入已排序的双向链表的适当位置。下面是代码的思想解释:
首先,我们定义了一个Node
类来表示链表中的节点。每个节点包含一个整数类型的data
字段,以及指向前一个节点和下一个节点的指针:prev
和next
。
接下来,我们定义了一个DoublyLinkedList
类,该类包含一个指向链表头部的指针head
。
在DoublyLinkedList
类中,我们定义了一个insertSorted
方法,该方法接受一个有序数组作为参数,并将其插入到已排序链表的适当位置。该方法的实现如下:
我们从数组的最后一个元素开始遍历,以便保持元素的相对顺序和插入位置的正确性。
newNode
,并将当前节点的值存储在新节点的data
字段中。next
指针指向当前链表的头节点head
,并检查链表是否为空。如果链表不为空,则将头节点的prev
指针指向新节点。重复以上步骤,直到遍历完整个数组。
在main
方法中,我们创建了一个有序数组arr
,即int[] arr = {1, 3, 5, 7, 9};
,然后创建一个DoublyLinkedList
对象list
。我们调用insertSorted
方法将该数组插入到已排序链表list
的适当位置。
使用头插法的主要思想是通过在插入新节点时,将新节点的next
指针指向当前链表的头节点,然后将当前链表的头节点的prev
指针指向新节点,最后将新节点设置为链表的新头节点。这样就能够保持元素的相对顺序,并插入到正确的位置,从而实现将有序数组插入到已排序的双向链表的适当位置。