這裏主要是記錄各類數據結構的結構體, 對於具體實現和講解往後回會以連接形式提供, 這裏只提供一個思惟樹, 創建一個數據結構的思惟體系, 後續更新歡迎關注 GitHub.node
typedef struct {
ElemType * elem;
int length;
int listsize;
} SqList;複製代碼
typedef struct LNode {
ElemType data;
struct LNode * next;
} LNode, * LinkList;複製代碼
typedef struct {
ElemType data;
int cur; // 遊標指向下一個元素的數組下標
} component, SlinkList[MAXSIZE];複製代碼
typedef struct DuLNode{
ElemType data;
struct DuLNode * prior;
struct DuLNode * next;
} DuLNode, * DuLinkList;複製代碼
typedef struct {
SELemType * base;
SElemType * top;##### int stacksize;
} SqStack;複製代碼
應用: 主要是利用先進後出的特性git
數制轉換github
括號匹配檢測面試
行編輯程序算法
迷宮非遞歸求解數組
表達式求值數據結構
Hanoi塔問題curl
typedef struct QNode {
QElemType data;
struct QNode * next;
} QNode, * QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
} LinkQueue;複製代碼
typedef struct {
QElemType * base;
int front;
int rear;
} SqQueue;複製代碼
typedef unsigned char SString[MAXSTRLEN + 1];
SString s;複製代碼
typedef struct {
char * ch;
int length;
}HString;複製代碼
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk * next;
} Chunk;
typedef struct {
Chunk * head;
Chunk * tail;
int curlen;
} LString;複製代碼
應用函數
- 子串定位 (KMP)
typedef struct {
ElemType * base;
int dim; // 數組維數
int * bounds; // 維界基址
int * constants; // 印象函數常量基址
} Array;複製代碼
討論稀疏矩陣的存儲優化
typedef struct {
int i;
int j;
ElemType e;
} Triple;
typedef struct {
Triple data[MAXSIZE + 1];
int mu; // 行
int nu; // 列
int tu; // 非零個數
}TSMatrix;複製代碼
typedef struct {
Triple data[MAXSIZE + 1];
int rpos[MAXRC + 1]; // 各行第一個非零元素位置表
int mu, nu, tu;
} RLSMatrix;複製代碼
typedef struct OLNode {
int i;
int j;
ElemType e;
struct OLNode * right; // 該非零元素所在行的右鏈域
struct OLNode * down; // 該非零元素所在列的下鏈域
} OLNode, * OLink;
typedef struct {
OLink * rhead; // 行鏈表頭指針地址
OLink * chead; // 列鏈表頭指針地址
int mu, nu, tu;
} CrossLink;複製代碼
表中有表
typedef enum { ATOM, LIST } ElemTag; // 0 : 原子, 1 : 子表
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom;
struct {
struct GLNode * hp; // 表頭
struct GLNode * tp; // 表尾
} ptr; // 表節點指針域
};
} * GList;複製代碼
typedef enum { ATOM, LIST } ElemTag; // 0 : 原子, 1 : 子表
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom;
struct {
struct GLNode * hp; // 表頭
} ptr; // 表節點指針域
};
struct GLNode * tp; // 表尾, 至關於 next.
} * GList;複製代碼
數組, 利用下標尋址
typedef TElemType SqBiTree[MAX_TREE_SIZE];複製代碼
typedef struct BiTNode {
TElemType data;
struct BiTNode * lchild;
struct BiTNode * rchild;
} BiTNode, * BiTree;複製代碼
根節點 -> 左子樹 -> 右子樹
左子樹 -> 根節點 -> 右子樹
左子樹 -> 右子樹 -> 根節點
算數表達式 a + b * (c - d) - e / f
前綴表達式-先序遍歷(逆波蘭 : - + a * b - cd / ef)
中綴表達式-中序遍歷(原表達式 : a + b * (c - d) - e / f)
後綴表達式-後續遍歷(逆波蘭式 : abcd - * + ef / -)
保存比遍歷過程當中的節點相關性結果
前驅後繼節點和左右孩子指示
lchild LTag data RTag rchild LTag 0 : lchild 域指示左孩子 1 : lchild 域指示前驅節點
RTag 0 : rchild 域指示右孩子 1 : rchild 域指示後繼節點
typedef enum PointerTag {Link, Thread}; // 0 : 指針 1 : 線索
typedef struct BiThrNode {
TElemType data;
struct BiThrNode * lchild;
struct BiThrNode * rchild;
PointerTag LTag;
PointerTag RTag;
} BiThrNode, * BiThrTree;複製代碼
typedef struct PTNode {
TElemType data;
int parent;
} PTNode;
typedef struct {
PTNode nodes[MAX_TREE_SIZE];
int r; // 根的位置
int n; // 節點數
} PTree;複製代碼
typedef struct CTNode { // 孩子節點
struct CTNode * next;
int child;
} * ChildPtr;
typedef struct {
TElemType data;
ChildPtr firstchild; // 孩子鏈表頭指針
} CTBox;
typedef struct {
CTBox nodes[MAX_TREE_SIZE];
int r; // 根的位置
int n; // 節點數
} CTree;複製代碼
typedef struct CSNode {
ElemType data;
struct CSNode * firstchild;
struct CSNode * nextsibling;
} CSNode, * CSTree;複製代碼
左孩子右兄弟(左右是對二叉樹而言, 孩子兄弟是對森林而言, 下面同理)
左孩子轉換成孩子, 右孩子轉換成兄弟
第一棵樹的根
先序遍歷第一棵樹中根節點的子樹森林
先序遍歷除第一棵樹剩餘的樹構成的森林
中序遍歷第一棵樹中根節點的子樹森林
第一棵樹的根
中序遍歷除第一棵樹剩餘的樹構成的森林
typedef enum {DG, DN, UDG, UDN} GraphKind; // {有向圖, 有向網, 無向圖, 無向網}
typedef struct ArcCell {
VRType adj; // 頂點相關類型. 無權圖 : 1/0 表示相鄰與否 帶權圖 : 權值信息
InfoType * info; // 該弧相關的指針
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
VertexType vexs[MAX_VERTEX_NUM]; // 頂點向量
AdjMatrix arcs; // 鄰接矩陣
int vexnum; // 頂點數
int arcnum; // 弧數
GraphKind kind; // 圖的種類標誌
} MGraph;複製代碼
表節點
adjvex nextarc info 頭結點
data firstarc
typedef struct ArcNode {
int adjvex; // 該弧所指向頂點位置
struct ArcNode * nextarc; // 指向下一條弧的指針
InfoType * info; // 該弧相關信息的指針
} ArcNode;
typedef struct VNode {
VertexType data; // 頂點信息
ArcNode * firstarc; // 指向第一條依附該頂點的弧的指針
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum; // 頂點數
int arcnum; // 弧數
int kind; // 種類標記
} ALGraph;複製代碼
弧節點
tailvex headvex hlink tlink info 頂點節點
data firstin firstout
typedef struct ArcBox {
int tailvex; // 該弧的尾頂點位置
int headvex; // 該弧的頭頂點位置
struct ArcBox * hlink; // 弧頭相同的弧的鏈域
struct ArcBox * tlink; // 弧尾相同的弧的鏈域
InfoType * info; // 該弧相關信息指針
} ArcBox;
typedef struct VexNode {
VertexType data;
ArcBox * firstin; // 指向該節點第一條入弧
ArcBox * firstout; // 指向該節點第一條出弧
} VexNode;
typedef struct {
VexNode xlist[MAX_VERTEX_NUM]; // 表頭向量
int vexnum; // 有向圖的當前頂點數
int arcnum; // 有向圖的當前弧數
} OLGraph;複製代碼
每一條邊用一個節點表示
mark ivex ilink jvex jlink info 每一個頂點用一個節點表示
data firstedge
typedef enum {unvisited, visited} VisitIf;
typedef struct EBox {
VisitIf mark; // 訪問標記
int ivex; // 依附頂點位置
int jvex; // 依附頂點位置
struct EBox * ilink; // 依附頂點的下一邊
struct EBox * jlink; // 依附頂點的下一邊
InfoType * info; // 該邊的信息指針
} EBox;
typedef struct VexBox {
VertexType data;
EBox * firstedge; // 指向第一條依附該頂點的邊
} VexBox;
typedef struct {
VexBox adjmulist[MAX_VERTEX_NUM];
int vexnum; // 無向圖的頂點數
int edgenum; // 無向圖的邊數
} AMLGraph複製代碼
以迷宮爲例子(面試中被問到, 印象比較深入). 深度優先就是一條路走到黑, 因此返回的第一條路徑不保證是最優解.
Boolean visited[MAX]; // 訪問標誌數組
Status (* VisiteFunc) (int v); // 韓阿叔變量
void DFSTraverse(Graph G, Status (* Visit)(int v)) { // 深度優先遍歷
VisitFunc = Visit; // 使用全局變量 VisitFunc, 使 DFS 沒必要設置函數指針參數
for (v = 0; v < G.vexnum; ++v) {
visited[v] = FALSE; // 訪問數組標誌初始化
}
for (v = 0; v < G.vexnum; ++v) {
if (!visited[v]) {
DFS(G, v); // 對未訪問的頂點調用 DFS
}
}
}
void DFS(Graph G, int v) { // 從第 v 個頂點出發遞歸的深度優先遍歷圖 G.
visited[v] = TRUE;
VisitFunc(v); // 訪問第 v 個頂點
for (w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
if (!visited[w]) {
DFS(G, w); // 對 v 的還沒有訪問的鄰接頂點 w 遞歸調用 DFS.
}
}
}複製代碼
有點層序遍歷的意思, 在遍歷完全部狀況下(能夠進行算法優化, 對有些狀況進行捨棄)能夠得出最優解.
void BFSTraverse(Graph G, Status (* Visit) (int v)) {
for (v= 0; v < G.vexnum; ++v) {
visited[v] = FALSE;
}
InitQueue(Q);
for (v = 0; v < G.vexnum; ++v) {
if (!visited[v]) {
visited[v] = TRUE;
Visit(v);
EnQueue(Q, v);
while (!QueueEmpty(Q)) {
DeQueue(Q, u);
for (w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w)) {
// w 爲 u 還沒有訪問的鄰接頂點
if (!visited[w]) {
visited[w] = TRUE;
Visit(w);
EnQueue(Q, w);
} // if
} // for
} // while
} // if
} // for
} // BFSTraverse複製代碼
// 如下待填
以點爲主: 主要是分爲兩個集合, 一個是已加入的節點, 另外一個是未加入節點. 在未加入的節點集合中找到一個離已加入集合最近的節點加入. 直至全部節點被加入.
以邊爲主: 初始條件是把圖的全部邊去除變成 V 個連通圖. 而後每次找一條代價最小的邊加入, 確保每加入一條邊連通圖個數都減小一個(也就是確保無環路)。直至成一個連通圖時就是最小生成樹.
主要是維護一個表和一個已加入路徑集合, 表記錄從原點到每個點的當前最小權值. 若是已加入路徑集合中的點經過某條路徑對未加入集合中的點的最小權值有影響則更新該節點權值. 最後在每次更新完成後判斷目前未加入集合中的最小權值節點加入集合, 再對該節點的邊所達的節點作如上判斷. 最終能夠求出起點到每個點的全部最短路徑.
主要是判斷通過該點到達的臨時目點的權值和該點目前權值(能夠不考慮是否已經通過, 可是循環只會掃一遍因此沒有什麼影響)的大小來判斷是否更新權值.
關鍵路徑和拓撲排序 (KeyWord : 鬆弛)