/**
 * data-structure-typed
 *
 * @author Pablo Zeng
 * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
 * @license MIT License
 */
import type { GraphOptions, VertexKey } from '../../types';
import { IGraph } from '../../interfaces';
import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
export declare class UndirectedVertex<V = any> extends AbstractVertex<V> {
    constructor(key: VertexKey, value?: V);
}
export declare class UndirectedEdge<E = number> extends AbstractEdge<E> {
    endpoints: [VertexKey, VertexKey];
    constructor(v1: VertexKey, v2: VertexKey, weight?: number, value?: E);
}
/**
 * Undirected graph implementation.
 * @template V - Vertex value type.
 * @template E - Edge value type.
 * @template VO - Concrete vertex class (extends AbstractVertex<V>).
 * @template EO - Concrete edge class (extends AbstractEdge<E>).
 * @remarks Time O(1), Space O(1)
 * @example
 * // basic UndirectedGraph vertex and edge creation
 *  // Create a simple undirected graph
 *     const graph = new UndirectedGraph<string>();
 *
 *     // Add vertices
 *     graph.addVertex('A');
 *     graph.addVertex('B');
 *     graph.addVertex('C');
 *     graph.addVertex('D');
 *
 *     // Verify vertices exist
 *     console.log(graph.hasVertex('A')); // true;
 *     console.log(graph.hasVertex('B')); // true;
 *     console.log(graph.hasVertex('E')); // false;
 *
 *     // Check vertex count
 *     console.log(graph.size); // 4;
 * @example
 * // UndirectedGraph edge operations (bidirectional)
 *  const graph = new UndirectedGraph<string>();
 *
 *     // Add vertices
 *     graph.addVertex('A');
 *     graph.addVertex('B');
 *     graph.addVertex('C');
 *
 *     // Add undirected edges (both directions automatically)
 *     graph.addEdge('A', 'B', 1);
 *     graph.addEdge('B', 'C', 2);
 *     graph.addEdge('A', 'C', 3);
 *
 *     // Verify edges exist in both directions
 *     console.log(graph.hasEdge('A', 'B')); // true;
 *     console.log(graph.hasEdge('B', 'A')); // true; // Bidirectional!
 *
 *     console.log(graph.hasEdge('C', 'B')); // true;
 *     console.log(graph.hasEdge('B', 'C')); // true; // Bidirectional!
 *
 *     // Get neighbors of A
 *     const neighborsA = graph.getNeighbors('A');
 *     console.log(neighborsA[0].key); // 'B';
 *     console.log(neighborsA[1].key); // 'C';
 * @example
 * // UndirectedGraph deleteEdge and vertex operations
 *  const graph = new UndirectedGraph<string>();
 *
 *     // Build a simple undirected graph
 *     graph.addVertex('X');
 *     graph.addVertex('Y');
 *     graph.addVertex('Z');
 *     graph.addEdge('X', 'Y', 1);
 *     graph.addEdge('Y', 'Z', 2);
 *     graph.addEdge('X', 'Z', 3);
 *
 *     // Delete an edge
 *     graph.deleteEdge('X', 'Y');
 *     console.log(graph.hasEdge('X', 'Y')); // false;
 *
 *     // Bidirectional deletion confirmed
 *     console.log(graph.hasEdge('Y', 'X')); // false;
 *
 *     // Other edges should remain
 *     console.log(graph.hasEdge('Y', 'Z')); // true;
 *     console.log(graph.hasEdge('Z', 'Y')); // true;
 *
 *     // Delete a vertex
 *     graph.deleteVertex('Y');
 *     console.log(graph.hasVertex('Y')); // false;
 *     console.log(graph.size); // 2;
 * @example
 * // UndirectedGraph connectivity and neighbors
 *  const graph = new UndirectedGraph<string>();
 *
 *     // Build a friendship network
 *     const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
 *     for (const person of people) {
 *       graph.addVertex(person);
 *     }
 *
 *     // Add friendships (undirected edges)
 *     graph.addEdge('Alice', 'Bob', 1);
 *     graph.addEdge('Alice', 'Charlie', 1);
 *     graph.addEdge('Bob', 'Diana', 1);
 *     graph.addEdge('Charlie', 'Eve', 1);
 *     graph.addEdge('Diana', 'Eve', 1);
 *
 *     // Get friends of each person
 *     const aliceFriends = graph.getNeighbors('Alice');
 *     console.log(aliceFriends[0].key); // 'Bob';
 *     console.log(aliceFriends[1].key); // 'Charlie';
 *     console.log(aliceFriends.length); // 2;
 *
 *     const dianaFriends = graph.getNeighbors('Diana');
 *     console.log(dianaFriends[0].key); // 'Bob';
 *     console.log(dianaFriends[1].key); // 'Eve';
 *     console.log(dianaFriends.length); // 2;
 *
 *     // Verify bidirectional friendship
 *     const bobFriends = graph.getNeighbors('Bob');
 *     console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
 *     console.log(bobFriends[1].key); // 'Diana';
 * @example
 * // UndirectedGraph for social network connectivity analysis
 *  interface Person {
 *       id: number;
 *       name: string;
 *       location: string;
 *     }
 *
 *     // UndirectedGraph is perfect for modeling symmetric relationships
 *     // (friendships, collaborations, partnerships)
 *     const socialNetwork = new UndirectedGraph<number, Person>();
 *
 *     // Add people as vertices
 *     const people: [number, Person][] = [
 *       [1, { id: 1, name: 'Alice', location: 'New York' }],
 *       [2, { id: 2, name: 'Bob', location: 'San Francisco' }],
 *       [3, { id: 3, name: 'Charlie', location: 'Boston' }],
 *       [4, { id: 4, name: 'Diana', location: 'New York' }],
 *       [5, { id: 5, name: 'Eve', location: 'Seattle' }]
 *     ];
 *
 *     for (const [id] of people) {
 *       socialNetwork.addVertex(id);
 *     }
 *
 *     // Add friendships (automatically bidirectional)
 *     socialNetwork.addEdge(1, 2, 1); // Alice <-> Bob
 *     socialNetwork.addEdge(1, 3, 1); // Alice <-> Charlie
 *     socialNetwork.addEdge(2, 4, 1); // Bob <-> Diana
 *     socialNetwork.addEdge(3, 5, 1); // Charlie <-> Eve
 *     socialNetwork.addEdge(4, 5, 1); // Diana <-> Eve
 *
 *     console.log(socialNetwork.size); // 5;
 *
 *     // Find direct connections for Alice
 *     const aliceConnections = socialNetwork.getNeighbors(1);
 *     console.log(aliceConnections[0].key); // 2;
 *     console.log(aliceConnections[1].key); // 3;
 *     console.log(aliceConnections.length); // 2;
 *
 *     // Verify bidirectional connections
 *     console.log(socialNetwork.hasEdge(1, 2)); // true;
 *     console.log(socialNetwork.hasEdge(2, 1)); // true; // Friendship works both ways!
 *
 *     // Remove a person from network
 *     socialNetwork.deleteVertex(2); // Bob leaves
 *     console.log(socialNetwork.hasVertex(2)); // false;
 *     console.log(socialNetwork.size); // 4;
 *
 *     // Alice loses Bob as a friend
 *     const updatedAliceConnections = socialNetwork.getNeighbors(1);
 *     console.log(updatedAliceConnections[0].key); // 3;
 *     console.log(updatedAliceConnections[1]); // undefined;
 *
 *     // Diana loses Bob as a friend
 *     const dianaConnections = socialNetwork.getNeighbors(4);
 *     console.log(dianaConnections[0].key); // 5;
 *     console.log(dianaConnections[1]); // undefined;
 */
export declare class UndirectedGraph<V = any, E = any, VO extends UndirectedVertex<V> = UndirectedVertex<V>, EO extends UndirectedEdge<E> = UndirectedEdge<E>> extends AbstractGraph<V, E, VO, EO> implements IGraph<V, E, VO, EO> {
    /**
     * Construct an undirected graph with runtime defaults.
     * @param options - `GraphOptions<V>` (e.g. `vertexValueInitializer`, `defaultEdgeWeight`).
     * @remarks Time O(1), Space O(1)
     */
    constructor(options?: Partial<GraphOptions<V>>);
    protected _edgeMap: Map<VO, EO[]>;
    get edgeMap(): Map<VO, EO[]>;
    set edgeMap(v: Map<VO, EO[]>);
    /**
     * Construct an undirected graph from keys with value initializer `v => v`.
     * @template K - Vertex key type.
     * @param keys - Iterable of vertex keys.
     * @returns UndirectedGraph with all keys added.
     * @remarks Time O(V), Space O(V)
     */
    static fromKeys<K extends VertexKey>(keys: Iterable<K>): UndirectedGraph<K, any, UndirectedVertex<K>, UndirectedEdge<any>>;
    /**
     * Construct an undirected graph from `[key, value]` entries.
     * @template V - Vertex value type.
     * @param entries - Iterable of `[key, value]` pairs.
     * @returns UndirectedGraph with all vertices added.
     * @remarks Time O(V), Space O(V)
     */
    static fromEntries<V>(entries: Iterable<[VertexKey, V]>): UndirectedGraph<V, any, UndirectedVertex<V>, UndirectedEdge<any>>;
    /**
     * Create an undirected vertex instance. Does not insert into the graph.
     * @param key - Vertex identifier.
     * @param value - Optional payload.
     * @returns Concrete vertex instance.
     * @remarks Time O(1), Space O(1)
     */
    createVertex(key: VertexKey, value?: VO['value']): VO;
    /**
     * Create an undirected edge instance. Does not insert into the graph.
     * @param v1 - One endpoint key.
     * @param v2 - The other endpoint key.
     * @param weight - Edge weight; defaults to `defaultEdgeWeight`.
     * @param value - Edge payload.
     * @returns Concrete edge instance.
     * @remarks Time O(1), Space O(1)
     */
    createEdge(v1: VertexKey, v2: VertexKey, weight?: number, value?: EO['value']): EO;
    /**
     * Get an undirected edge between two vertices, if present.
     * @param v1 - One vertex or key.
     * @param v2 - The other vertex or key.
     * @returns Edge instance or `undefined`.
     * @remarks Time O(1) avg, Space O(1)
     */
    getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined;
    /**
     * Delete a single undirected edge between two vertices.
     * @param v1 - One vertex or key.
     * @param v2 - The other vertex or key.
     * @returns Removed edge or `undefined`.
     * @remarks Time O(1) avg, Space O(1)
     */
    deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined;
    /**
     * Delete an edge by instance or by a pair of keys.
     * @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
     * @param otherSideVertexKey - Required second endpoint when deleting by pair.
     * @returns Removed edge or `undefined`.
     * @remarks Time O(1) avg, Space O(1)
     */
    deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined;
    /**
     * Delete a vertex and remove it from all neighbor lists.
     * @param vertexOrKey - Vertex or key.
     * @returns `true` if removed; otherwise `false`.
     * @remarks Time O(deg), Space O(1)
     */
    deleteVertex(vertexOrKey: VO | VertexKey): boolean;
    /**
     * Degree of a vertex (# of incident undirected edges).
     * @param vertexOrKey - Vertex or key.
     * @returns Non-negative integer.
     * @remarks Time O(1) avg, Space O(1)
     */
    degreeOf(vertexOrKey: VertexKey | VO): number;
    /**
     * Incident undirected edges of a vertex.
     * @param vertexOrKey - Vertex or key.
     * @returns Array of incident edges.
     * @remarks Time O(deg), Space O(deg)
     */
    edgesOf(vertexOrKey: VertexKey | VO): EO[];
    /**
     * Unique set of undirected edges across endpoints.
     * @returns Array of edges.
     * @remarks Time O(E), Space O(E)
     */
    edgeSet(): EO[];
    getNeighbors(vertexOrKey: VO | VertexKey): VO[];
    /**
     * Resolve an edge's two endpoints to vertex instances.
     * @param edge - Edge instance.
     * @returns `[v1, v2]` or `undefined` if either endpoint is missing.
     * @remarks Time O(1), Space O(1)
     */
    getEndsOfEdge(edge: EO): [VO, VO] | undefined;
    /**
     * Whether the graph has no vertices and no edges.
     * @remarks Time O(1), Space O(1)
     */
    isEmpty(): boolean;
    /**
     * Remove all vertices and edges.
     * @remarks Time O(V + E), Space O(1)
     */
    clear(): void;
    /**
     * Deep clone as the same concrete class.
     * @returns A new graph of the same concrete class (`this` type).
     * @remarks Time O(V + E), Space O(V + E)
     */
    clone(): this;
    /**
     * Tarjan-based bridge and articulation point detection.
     * @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
     * @remarks Time O(V + E), Space O(V + E)
     */
    tarjan(): {
        dfnMap: Map<VO, number>;
        lowMap: Map<VO, number>;
        bridges: EO[];
        cutVertices: VO[];
    };
    /**
     * Get bridges discovered by `tarjan()`.
     * @returns Array of edges that are bridges.
     * @remarks Time O(B), Space O(1)
     */
    getBridges(): EO[];
    /**
     * Get articulation points discovered by `tarjan()`.
     * @returns Array of cut vertices.
     * @remarks Time O(C), Space O(1)
     */
    getCutVertices(): VO[];
    /**
     * DFN index map computed by `tarjan()`.
     * @returns Map from vertex to DFN index.
     * @remarks Time O(V), Space O(V)
     */
    getDFNMap(): Map<VO, number>;
    /**
     * LOW link map computed by `tarjan()`.
     * @returns Map from vertex to LOW value.
     * @remarks Time O(V), Space O(V)
     */
    getLowMap(): Map<VO, number>;
    /**
     * Internal hook to attach an undirected edge into adjacency maps.
     * @param edge - Edge instance.
     * @returns `true` if both endpoints exist; otherwise `false`.
     * @remarks Time O(1) avg, Space O(1)
     */
    protected _addEdge(edge: EO): boolean;
}
