日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构(2)

發布時間:2024/1/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 樹和二叉樹
    • 二叉樹
    • 哈夫曼樹編碼和譯碼
    • 知識理解
    • 鄰接矩陣的存儲和遍歷
    • 鄰接表存儲結構和遍歷
    • dijkstra算法求最短路徑
  • 查找和排序
    • 折半查找法
    • 二叉排序樹查找法
    • 折半查找插入法
    • 冒泡排序

樹和二叉樹

二叉樹

2.二叉樹的基本操作(6學時):
(1)采用二叉鏈表結構建立二叉樹;
(2)編程實現二叉樹的先序、中序、后序和層序遍歷;
(3 ) 編程實現非遞歸中序遍歷
(4)編程實現:求二叉樹的高度和葉子結點個數;

#include <iostream> using namespace std; typedef char elemType;//樹 結點 struct BitNode {elemType data;//結點數據域BitNode* lChild;BitNode* rChild;//左右孩子指針 }; typedef BitNode* BitTree;// 隊結點 struct QueueNode {BitNode* data;QueueNode* next; }; //隊列 struct LinkQueue {QueueNode* rear;QueueNode* front; }; //初始化一個隊 void initial(LinkQueue&); //入隊 void enLinkQueue(BitNode&, LinkQueue& ); //出隊 BitTree deLinkQueue(LinkQueue& Q);//棧 struct StackNode {BitNode* data;StackNode* next; }; typedef StackNode* Stack; //入棧 void push(Stack&); //出棧 BitTree pop(Stack&); //得到棧頂元素 BitTree gettop(Stack&);//利用 擴展先序遍歷序列 創建二叉樹 void creat(BitTree &bit); //先序遍歷 void preOderTraverse(BitTree& bit); //中序遍歷 void inOderTraverse(BitTree& bit); //后序遍歷 void postOderTraverse(BitTree& bit); //層次遍歷 void layerTraverse(BitTree& bit); //中序非遞歸遍歷 void nonrecursiveInOderTraverse(BitTree& bit); //求樹的深度 int treeHeight(BitTree& bit); //求樹的葉子結點個數 int treeLeafSize(BitTree& bit);int main() {BitTree bit;bit = new BitNode;cout << "請輸入 擴展先序遍歷序列:" << endl;creat(bit);cout << "先序遍歷" << endl;preOderTraverse(bit);cout << endl;cout << "中序遍歷" << endl;inOderTraverse(bit);cout << endl;cout << "后序遍歷" << endl;postOderTraverse(bit);cout << endl;cout << "層次遍歷" << endl;layerTraverse(bit);cout << endl;cout << "非遞歸中序遍歷" << endl;nonrecursiveInOderTraverse(bit);cout << endl;cout << "樹的深度" << endl;cout<<treeHeight(bit);cout << endl;cout << "樹的葉子結點數" << endl;cout << treeLeafSize(bit);cout << endl; }void creat(BitTree& bit) {char ch;ch = getchar();if (ch == '#') bit = NULL;else {bit = new BitNode;bit->data = ch;creat(bit->lChild);creat(bit->rChild);} }void preOderTraverse(BitTree& bit) {if (bit) {//如果二叉樹非空cout << bit->data;preOderTraverse(bit->lChild);preOderTraverse(bit->rChild);} }void inOderTraverse(BitTree& bit) {if (bit) {//如果二叉樹非空inOderTraverse(bit->lChild);cout << bit->data;inOderTraverse(bit->rChild);} }void postOderTraverse(BitTree& bit) {if (bit) {//如果二叉樹非空postOderTraverse(bit->lChild);postOderTraverse(bit->rChild);cout << bit->data;} }void initial(LinkQueue& Q) {//構造一個空隊列Q//生成新的結點作為頭節點,隊列的頭指針和尾指針都指向該結點Q.front = Q.rear = new QueueNode;//頭節點的指針域置為空Q.front->next = NULL; } void enLinkQueue(BitTree& bit, LinkQueue& Q) {//為入隊元素分配結點空間,用指針p指向QueueNode* p = new QueueNode;p->data = bit; //將新結點數據置為樹結點p->next = NULL;Q.rear->next = p;//將新結點插入到隊尾Q.rear = p;//修改隊尾指針 } BitTree deLinkQueue( LinkQueue& Q) {//返回隊頭的樹結點BitNode* e;//是否隊空if (Q.rear == Q.front) return NULL;//臨時保存隊頭元素空間以備釋放//p 指向隊頭元素QueueNode* p;p = Q.front->next;//e 保存隊頭元素的值e = p->data;//修改頭指針的指針域,指向下一個結點Q.front->next = p->next;//如果最后一個元素被刪,隊尾指針指向頭節點if (Q.rear == p) Q.rear = Q.front;delete p;//釋放原隊頭元素的空間return e; } void layerTraverse(BitTree& bit) {if (bit) {//如果二叉樹非空//新建并初始化隊列LinkQueue Q;initial(Q); //訪問根節點cout << bit->data;//如果存在左孩子就把左孩子入隊if (bit->lChild) enLinkQueue(bit->lChild, Q);//如果存在右孩子就把右孩子入隊if (bit->rChild) enLinkQueue(bit->rChild, Q);//出隊一個結點 //如果當前結點不為空BitTree b;while (b=deLinkQueue(Q)){//訪問當前結點cout << b->data;//如果存在左孩子就把左孩子入隊if (b->lChild) enLinkQueue(b->lChild, Q);//如果存在右孩子就把右孩子入隊if (b->rChild) enLinkQueue(b->rChild, Q);} } }void push(Stack& S,BitTree& bit) {Stack p = new StackNode;//生成一個新結點p->data = bit;//將新結點數據域置為ep->next = S;//將新節點插入棧頂S = p;//修改棧頂指針為p } BitTree pop(Stack& S) {BitTree b;b = S->data; //將棧頂元素賦給bStack p = S; //臨時保存棧頂元素的空間以備釋放S = p->next; //修改棧頂指針,指向新的棧頂元素delete p; //釋放原棧頂元素的空間return b; } BitTree gettop(Stack& S) {BitTree b;b = S->data; //將棧頂元素賦給breturn b; } void nonrecursiveInOderTraverse(BitTree& bit) {//新建棧,根指針入棧Stack S = NULL;push(S, bit);BitTree b;//當棧非空時while (S){//當棧頂非空時,把棧頂的左孩子入棧 (結束的時候棧頂為空)while (b=gettop(S)){push(S, b->lChild);}//把棧頂的空指針出棧b=pop(S); if (S) {//如果棧非空//棧頂出棧并訪問b = pop(S);cout << b->data;//棧頂的右孩子入棧push(S, b->rChild); }} }int treeHeight(BitTree& bit) {if (bit == NULL){//空樹return 0;}if (bit->lChild == NULL && bit->rChild == NULL){return 1;}int lHeight = treeHeight(bit->lChild);int rHeight = treeHeight(bit->rChild);//左右子樹誰的高度高就返回誰的值 +1是當前結點的一層return 1 + (lHeight > rHeight ? lHeight : rHeight); }int treeLeafSize(BitTree& bit) {if (bit) {//如果二叉樹非空if ((bit->lChild == NULL) && (bit->rChild == NULL)) {return 1;}return treeLeafSize(bit->lChild) + treeLeafSize(bit->rChild);}else {return 0;}}

哈夫曼樹編碼和譯碼

  • 創建 先把所有葉子節點初始化,存進一個哈夫曼樹數組,然后選擇兩個權值最小的子樹合并成新樹加入數組(總結點數2n-1)
  • 編碼 (從葉子結點起,向上找父母,如果是父母的左孩子就編碼0,反之編碼1,編碼串的設置很有借鑒意義,利用start和length
  • 譯碼 (由編碼從根節點開始0向左1向右遍歷,如果是葉子結點就輸出,然后重新從根節點遍歷
#include <iostream> using namespace std; #define MAXVALUE 2000 // 最大權值 //#define MAXBIT 20 // 哈夫曼編碼最大程度 //哈夫曼樹 struct Htreetype {char ch;int weight;int parent;int Lchild, Rchild; }; //哈夫曼編碼串 struct Hcodetype {char bit[100];// 位串int start; // 編碼在位串中的起始位置char ch; }; // 選擇權值最小的結點 void select(Htreetype t[], int tlength, int* p1, int* p2) {*p1 = *p2 = 0;int small1, small2;small1 = small2 = MAXVALUE;for (int i = 0 ; i < tlength; i++){if (t[i].parent == -1){if (t[i].weight < small1){small2 = small1;small1 = t[i].weight;*p2 = *p1;*p1 = i;}else if (t[i].weight < small2){small2 = t[i].weight;*p2 = i;}}} } //創建哈夫曼樹 void HuffmanTree(Htreetype t[], int tlength,int length, char chs[], int weights[]) // 構造哈夫曼樹數組 {int p1, p2;p1 = p2 = 0;//初始化 哈夫曼樹for (int i = 0; i < length; i++) {t[i].Lchild = -1;t[i].parent = -1;t[i].Rchild = -1;t[i].ch = chs[i];t[i].weight = weights[i];}// 構造哈夫曼樹for (int i = length; i < tlength; i++) {select(t, i, &p1, &p2);t[p1].parent = i;t[p2].parent = i;t[i].Lchild = p1;t[i].Rchild = p2;t[i].weight = t[p1].weight + t[p2].weight;t[i].parent = -1;} } //創建哈夫曼編碼 void HuffmanCode(Hcodetype code[], Htreetype t[], int tlength, int length, char chs[], int weights[]) {int i, c, p;Hcodetype cd; // 緩沖變量,暫時存儲HuffmanTree(t,tlength,length,chs,weights);for (i = 0; i < length; i++){cd.start = length;cd.ch = t[i].ch;c = i; // 從葉子結點向上p = t[i].parent; // t[p]是t[i]的雙親while (p != -1){cd.start--;if (c == t[p].Lchild)cd.bit[cd.start] = '0'; //左子樹編為0;elsecd.bit[cd.start] = '1'; //右子樹編為1;c = p; // 移動p = t[c].parent;}code[i] = cd; // 第i + 1個字符的編碼存入code} } //輸出編制的哈夫曼編碼 void show(Htreetype t[], Hcodetype code[],int length,string codestr[][2]) {for (int i = 0; i < length; i++){codestr[i][0] = code[i].ch;cout << codestr[i][0] << ": ";string s = "";for (int j = code[i].start; j < length; j++){s+= code[i].bit[j];}codestr[i][1] = s;cout << codestr[i][1] << endl;} } //輸入句子輸出哈夫曼編碼 void encode( Hcodetype code[], int length,string codestr[][2]) {cout << "模擬發送端" << endl;cout << " 輸入:";char a[50];cin.getline(a, 50); //接受含空格的字符串cout << " 輸出:";for (int i = 0; i < 50; i++) {for (int j = 0; j < length; j++) {string m;m += a[i];if (m == codestr[j][0]) {cout << codestr[j][1];break;}}}cout << endl; } //輸入哈夫曼編碼輸出句子 void decode(Htreetype t[], Hcodetype code[], int tlength) {cout << "模擬接收端" << endl;cout << " 輸入:";char a[500];cin.getline(a, 500); //接受含空格的字符串cout << " 輸出:";//從根節點開始,0向左遍歷,1向右,遇到葉子結點輸出int current = tlength - 1;//t[current]是根結點for (int i = 0; i < 500; i++) {char next = a[i];if(next==NULL) break;if (next == '0') current = t[current].Lchild;else current = t[current].Rchild;if (t[current].Lchild == -1 && t[current].Rchild == -1) {cout << t[current].ch;current = tlength - 1;//int current =。。。。在這里有int時輸出第二個ch就有問題了}}}int main(){//被編碼字符char chs[27];for (int i = 0; i <26; i++) {chs[i] = 'a' + i;}chs[26] = ' ';//被編碼字符對應權重int weights[27] = { 64, 13, 22, 32, 103, 21, 15,47, 57, 1, 5, 32, 20, 57, 63, 15, 1, 48, 51,80, 23, 8, 18, 1, 16, 1, 168 };const int length=27, tlength = 2 * length - 1;Htreetype t[tlength];//聲明哈夫曼樹的數組Hcodetype code[length];//聲明字符編碼的數組string codestr[length][2];//保存編碼的數組HuffmanCode(code, t,tlength,length,chs,weights);//創建哈夫曼樹及其編碼cout << "輸出編制的哈夫曼編碼" << endl;show(t, code,length,codestr);encode(code, length, codestr);decode(t, code, tlength);return 0;}

知識理解

  • 圖的存儲結構
    鄰接矩陣存儲:一個數組存儲頂點,一個矩陣存儲頂點之間的邊及邊的權值。行列數均為頂點數的矩陣,對應位置的元素表示行列兩個點之間邊的權值,如果兩點之間沒有邊,該位置元素設置為無限大。如果是無向圖就是對稱矩陣。
    鄰接表:一個頂點結構 的數組,也就是頭結點表。一般頭節點連接的邊結點都是出邊,存儲時,生成邊結點插到頭節點上。
  • 深度優先遍歷 類似于樹的先序遍歷,根左右,在圖里“左右”的順序是取決于存儲時的順序。先訪問該頂點,輸出頂點之后利用visted數組對該頂點做訪問標記,然后訪問它的鄰接點,這樣遞歸下去。
  • 廣度優先遍歷類似于樹的層序遍歷,利用隊列。把第一個頂點入隊,然后出隊并訪問,輸出頂點之后利用visted數組對該頂點做訪問標記,然后把它所有的鄰接點都入隊。接著,出隊一個頂點如果對應visted數組未被標記就訪問,輸出頂點之后利用visted數組對該頂點做訪問標記,然后把它所有的鄰接點都入隊。重復直到隊列為空。
  • 拓撲排序 按照先后順序(有向圖)給遍歷排序,不唯一,能判斷是否有回路(遍歷完的頂點數小于圖的總數)。核心思想是重復選擇沒有前驅的頂點,刪除該頂點和以該頂點為起點的弧。AOV網 頂點表示活動,弧表示優先關系。
  • AOE網邊表示活動,(邊的權值表示活動持續時間)頂點表示事件
    關鍵路徑 源點(沒有入度的頂點)到匯點(沒有出度的頂點)最長的路徑。關鍵路徑所用時間也是這個工程最少的時間,因為只要花費時間最長的都完成了,這個工程才會完成。
    **ve(i),vl(i)**為事件發生的最早時間(源點到頂點i的最長路徑的長度)和最晚時間(在關鍵路徑上,匯點到頂點i的逆拓撲序列,關鍵路徑長度減去匯點到該點的最長路徑長度)
    e(i),l(i) 活動發生的最早時間和最晚時間。最早時間:源點到活動起點的最長路徑長度。最晚時間:關鍵路徑長度 減去 匯點到起點的最長路徑長度。活動i的松弛時間 l(i)-e(i).
  • Dijstra算法 填表格:


    選擇一個點作為起點,這個選擇的是a,A,可以分別到達bcd三個點,在表格中填寫相應的權值和路徑,選擇其中最小的C加入終點集。第二步,從c點開始c可以到e和f點,從c開始不能到達的點,它的路徑還按照上一列寫,經過c點可以到達的點的路徑的權值和上一列相比哪個權值小填寫哪個。再在這一列選擇最小的f加入中點集。以f為起點同上。。。。

鄰接矩陣的存儲和遍歷

# include<iostream>; using namespace std; #define MaxVertexNum 50 //最大頂點數 #define MaxInt 32767 //表示極大值 typedef char VertexType;//假設頂點的數據類型為字符型 typedef int ArcType; //假設邊的權值類型為整型 int visted[MaxVertexNum];//全局變量初始化會自動全部設置為0 //visted數組置0 void newVisted(int visted[MaxVertexNum]); // 隊結點 struct QueueNode {int data;QueueNode* next; }; //隊列 struct LinkQueue {QueueNode* rear;QueueNode* front; }; //初始化一個隊 void initial(LinkQueue&); //入隊 void enLinkQueue(int, LinkQueue&); //出隊 int deLinkQueue(LinkQueue& Q);//鄰接矩陣的存儲表示 struct AMGraph {VertexType vertices[MaxVertexNum];//頂點表ArcType arcs[MaxVertexNum][MaxVertexNum];//鄰接矩陣int vertexNum, arcNum;//圖的頂點和邊數int kind;//kind=0為無向圖,=1為有向圖 }; //創建圖 void creatAMGraph(AMGraph&); //返回輸入頂點的位置 int locateVex(AMGraph&, VertexType); //深度優先遍歷 void DFS_AM(AMGraph, int); //廣度優先遍歷 void BFS_AM(AMGraph, int);int main() {cout << "test" << endl;AMGraph G;creatAMGraph(G);cout << "深度優先遍歷:";DFS_AM(G,0);cout << endl;newVisted(visted);cout << "廣度優先遍歷:";BFS_AM(G,0);cout << endl; }void newVisted(int visted[MaxVertexNum]) {for (int i = 0; i < MaxVertexNum; i++) {visted[i] = 0;} }void creatAMGraph(AMGraph& G) {//采用鄰接矩陣表示法,創建無向網G cout << "輸入總頂點數:";cin >> G.vertexNum;cout << "輸入總邊數";cin >> G.arcNum;cout << endl;cout << "依次輸入頂點的信息:";for (int i = 0; i < G.vertexNum; i++) {cin >> G.vertices[i];}cout << "如果是無向圖請輸入0,有向圖輸入1:";cin >> G.kind;//初始化鄰接矩陣,邊的權值均為極大值for (int i = 0; i < G.vertexNum; i++) {for (int j = 0; j < G.vertexNum; j++) {G.arcs[i][j] = MaxInt;}}//構造鄰接矩陣 for (int k = 0; k < G.arcNum; k++) {cout << "輸入一條邊依附的頂點和權值:";VertexType v1, v2;ArcType w;cin >> v1 >> v2 >> w;int i, j;i = locateVex(G, v1);j = locateVex(G, v2); //確定v1和v2在G中的位置if ((i == -1) || (j == -1)) {cout << "請輸入正確信息";k--;}else {G.arcs[i][j] = w; //邊<v1, v2>的權值置為w if (G.kind == 0) {G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的對稱邊<v2, v1>的權值為w }}cout << endl;} } int locateVex(AMGraph& G, VertexType v) {for (int i = 0; i < G.vertexNum; i++) {if (v == G.vertices[i]) {return i;}}return -1; }void DFS_AM(AMGraph G, int v) {//圖G為鄰接矩陣類型 //訪問第v個頂點cout << G.vertices[v] << " ";visted[v] = 1;int c = v;//依次檢查鄰接矩陣v所在的行 for (int w = 0; w < G.vertexNum; w++) {if ((G.arcs[v][w] != MaxInt) && (visted[w] == 0)) {DFS_AM(G, w); //w是v的鄰接點,如果w未訪問,則遞歸調用DFS }} }void initial(LinkQueue& Q) {//構造一個空隊列Q//生成新的結點作為頭節點,隊列的頭指針和尾指針都指向該結點Q.front = Q.rear = new QueueNode;//頭節點的指針域置為空Q.front->next = NULL; } void enLinkQueue(int v, LinkQueue& Q) {//為入隊元素分配結點空間,用指針p指向QueueNode* p = new QueueNode;p->data = v; //將新結點數據置為頂點p->next = NULL;Q.rear->next = p;//將新結點插入到隊尾Q.rear = p;//修改隊尾指針 } int deLinkQueue(LinkQueue& Q) {//是否隊空if (Q.rear == Q.front) return NULL;//臨時保存隊頭元素空間以備釋放//p 指向隊頭元素QueueNode* p;p = Q.front->next;//e 保存隊頭元素的值int e = p->data;//修改頭指針的指針域,指向下一個結點Q.front->next = p->next;//如果最后一個元素被刪,隊尾指針指向頭節點if (Q.rear == p) Q.rear = Q.front;delete p;//釋放原隊頭元素的空間return e; } void BFS_AM(AMGraph G, int v) {//新建并初始化隊列LinkQueue Q;initial(Q);enLinkQueue(v, Q);//第v 個頂點入隊//訪問第v個頂點cout << G.vertices[v] << " ";visted[v] = 1;//把第v個頂點的鄰接點入隊for (int w = 0; w < G.vertexNum; w++) {if ((G.arcs[v][w] != MaxInt) && (visted[w] == 0)) {enLinkQueue(w, Q);}}int c = deLinkQueue(Q);//把第v個頂點出隊while (Q.length!=0)//隊非空時,出隊一個頂點{c = deLinkQueue(Q);if (visted[c] == 0) {//如果該頂點未被訪問過//訪問當前出隊的頂點cout << G.vertices[c] << " ";visted[c] = 1;//把第c個頂點的鄰接點入隊for (int w = 0; w < G.vertexNum; w++) {if ((G.arcs[c][w] != MaxInt) && (visted[w] == 0)) {enLinkQueue(w, Q);}}}} }


  • 問題與解決:
    調式的時候務必斷點調試每次輸入測試數據都要輸好久。。。while()里面,對于c++來說0就是非,注意判斷條件最好不要是某個變量。

鄰接表存儲結構和遍歷

# include<iostream>; using namespace std; #define MaxVertexNum 50 //最大頂點數 #define MaxInt 32767 //表示極大值 typedef char VertexType;//假設頂點的數據類型為字符型 typedef int ArcType; //假設邊的權值類型為整型 int visted[MaxVertexNum]; //visted數組置0 void newVisted(int visted[MaxVertexNum]); // 隊結點 struct QueueNode {int data;QueueNode* next; }; //隊列 struct LinkQueue {QueueNode* rear;QueueNode* front;int length; }; //初始化一個隊 void initial(LinkQueue&); //入隊 void enLinkQueue(int, LinkQueue&); //出隊 int deLinkQueue(LinkQueue& Q); //鄰接表的存儲表示 //邊結構 struct ArcNode {int adjvex;//該邊所指向的頂點位置struct ArcNode* next;//指向下一條邊的指針ArcType info;//和邊相關的信息,權值 }; //頂點結構 struct VNode {VertexType data;//頂點信息ArcNode* firstArc;//指向依附該頂點的第一條弧的指針 }; //圖結構 struct ALGraph {VNode vertices[MaxVertexNum];//鄰接表int vexNum, arcNum;//頂點數和弧數int kind;//圖的種類 }; //創建圖 int locateVex(ALGraph& G, VertexType v); void CreatALGraph(ALGraph&); //深度優先遍歷 void DFS_AL(ALGraph, int); //廣度優先遍歷 void BFS_AL(ALGraph, int);int main() {cout << "1812030065-李詩雨" << endl;ALGraph G;CreatALGraph(G);cout << "深度優先遍歷:";DFS_AL(G, 0);cout << endl;newVisted(visted);cout << "廣度優先遍歷:";BFS_AL(G, 0);cout << endl; }void newVisted(int visted[MaxVertexNum]) {for (int i = 0; i < MaxVertexNum; i++) {visted[i] = 0;} }void CreatALGraph(ALGraph& G) {cout << "輸入總頂點數:";cin >> G.vexNum;cout << "輸入總邊數";cin >> G.arcNum;cout << endl;cout << "依次輸入頂點的信息:";for (int i = 0; i < G.vexNum; ++i) { //輸入各點,構造頭結點表 cin >> G.vertices[i].data; //輸入頂點值 G.vertices[i].firstArc = NULL; //初始化表頭結點的指針域為NULL }cout << "如果是無向圖請輸入0,有向圖輸入1:";cin >> G.kind;for (int k = 0; k < G.arcNum; k++) { //輸入各邊,構造鄰接表 cout << "輸入一條邊依附的頂點和權值:";VertexType v1, v2;ArcType w;cin >> v1 >> v2 >> w;int i, j;i = locateVex(G, v1);j = locateVex(G, v2); //確定v1和v2在G中的位置if ((i == -1) || (j == -1)) {cout << "請輸入正確信息";k--;}else {ArcNode* p1=new ArcNode; //生成一個新的邊結點*p1 p1->adjvex = j; //鄰接點序號為j p1->info = w;p1->next = G.vertices[i].firstArc;G.vertices[i].firstArc= p1;//將新結點*p1插入頂點vi的邊表頭部if (G.kind == 0) {ArcNode* p2=new ArcNode; //生成一個新的邊結點*p2p2->adjvex = i; //鄰接點序號為ip2->info = w;p2->next = G.vertices[i].firstArc;G.vertices[j].firstArc = p2;//將新結點*p2插入頂點vj的邊表頭部}}cout << endl;} }int locateVex(ALGraph& G, VertexType v) {for (int i = 0; i < G.vexNum; i++) {if (v == G.vertices[i].data) {return i;}}return -1; }void DFS_AL(ALGraph G, int v) {//訪問第v個頂點cout << G.vertices[v].data << " ";visted[v] = 1;ArcNode* p = G.vertices[v].firstArc;; //p 指向 v 的邊鏈表的第一個邊結點 if (p != NULL) {//邊結點非空 if (visted[p->adjvex] == 0) {DFS_AL(G, p->adjvex);//如果v的鄰接點 未訪問,則遞歸調用DFS }p = p->next;; //p 指向下一個邊結點 if (visted[p->adjvex] == 0) {DFS_AL(G, p->adjvex);//如果v的鄰接點 未訪問,則遞歸調用DFS }} }void initial(LinkQueue& Q) {//構造一個空隊列Q//生成新的結點作為頭節點,隊列的頭指針和尾指針都指向該結點Q.front = Q.rear = new QueueNode;//頭節點的指針域置為空Q.front->next = NULL;Q.length = 0; } void enLinkQueue(int v, LinkQueue& Q) {//為入隊元素分配結點空間,用指針p指向QueueNode* p = new QueueNode;p->data = v; //將新結點數據置為頂點p->next = NULL;Q.rear->next = p;//將新結點插入到隊尾Q.rear = p;//修改隊尾指針Q.length++; } int deLinkQueue(LinkQueue& Q) {//是否隊空if (Q.rear == Q.front) return NULL;//臨時保存隊頭元素空間以備釋放//p 指向隊頭元素QueueNode* p;p = Q.front->next;//e 保存隊頭元素的值int e = p->data;//修改頭指針的指針域,指向下一個結點Q.front->next = p->next;//如果最后一個元素被刪,隊尾指針指向頭節點if (Q.rear == p) Q.rear = Q.front;delete p;//釋放原隊頭元素的空間Q.length--;return e; }void BFS_AL(ALGraph G, int v) {//新建并初始化隊列LinkQueue Q;initial(Q);//第v 個頂點入隊enLinkQueue(v, Q);//把第v個頂點的鄰接點也入隊ArcNode* arc = G.vertices[v].firstArc;while (arc != NULL) {enLinkQueue(arc->adjvex, Q);arc = arc->next;}v = deLinkQueue(Q);//把第v個頂點出隊//訪問第v個頂點cout << G.vertices[v].data << " ";visted[v] = 1;//如果隊非空,出隊一個頂點結點,如果該頂點未被訪問過,訪問該頂點,然后把該頂點的鄰接頂點入隊while (Q.length!=0){v = deLinkQueue(Q);if (visted[v] == 0) {//訪問當前出隊的頂點cout << G.vertices[v].data << " ";visted[v] = 1;//把第v個頂點的鄰接點入隊ArcNode* arc = G.vertices[v].firstArc;while (arc != NULL) {enLinkQueue(arc->adjvex, Q);arc = arc->next;}}} }


  • 問題與解決: 存儲的時候注意邊結點的鏈表是怎么增加的,深度優先遍歷要理解遞歸。

dijkstra算法求最短路徑

  • 理解:求最短路徑跟上面的表一樣的原理。直接看代碼吧
  • 問題:輸出方面:我第一個想法是正向找,v0到vi,當第i行輸出到vi就停止輸出。但是只要手動實現一遍而且找了一個包含情況多的例子就會發現問題。當我意識到要倒著從vi回到v0的時候很容易就想到了再加一個數組。重要的是:先手動實現算法,測試的時候用一個更普遍的例子

基于鄰接矩陣的dijkstra算法求最短路徑。

void ShortestPath_DIJ(AMGraph G, int v0) {//用Dijkstra算法求有向網G的v0頂點到其余頂點的最短路徑 int n = G.vertexNum; //n為G中頂點的個數 bool S[MaxVertexNum]; //終點集,作為目前最短路徑上已經訪問過的頂點標記int D[MaxVertexNum]; //保存v0到各個終點的最短路徑長度,例如D(2)的值為v0到v2的最短路徑int Path[MaxVertexNum]; //保存每個頂點的前驅頂點的編號//n 個頂點依次初始化 for (int v = 0; v < n; ++v) { S[v] = false; //S 初始為空集 D[v] = G.arcs[v0][v]; //將v0到各個終點的最短路徑長度初始化 if (D[v] < MaxInt) Path[v] = v0; //v0和v之間有弧,將v的前驅置為v0 else Path[v] = -1; //如果v0和v之間無弧,則將v的前驅置為-1 }S[v0] = true; //將v0加入S D[v0] = 0; //源點到源點的距離為0 int v;/*―開始主循環,每次求得v0到某個頂點v的最短路徑,將v加到S集―*/for (int i = 1; i < n; ++i) {//對其余n?1個頂點,依次進行計算 int min = MaxInt;//找到v0經過一條弧到的最短路徑到達的終點vfor (int w = 0; w < n; ++w) {if (!S[w] && D[w] < min)//如果未加入S且v0和vi間有弧{v = w; min = D[w];} //選擇一條當前的最短路徑,終點為v }S[v] = true; //將v加入S for (int w = 0; w < n; ++w) {//更新從v0出發到集合V?S上所有頂點的最短路徑長度 if (!S[w] && (D[v] + G.arcs[v][w] < D[w])) {D[w] = D[v] + G.arcs[v][w]; //更新D[w] Path[w] = v; //更改w的前驅為v }}}//輸出最短路徑for (int i = 1; i < G.vertexNum; i++) {int a[MaxVertexNum];//存放v0到vi的最短路徑的數組int k = i; //用來在path路徑中從vi往v0回溯查找a[0] = i; //vi 終點int j = 1; //存放v0到vi的最短路徑數組的下標for (;;) {a[j] = Path[k];k = a[j];if (k == -1) {//說明a[j-1]==0break;}j++;}cout << endl;for (int k = j - 1; k >= 0; k--) {//倒序從v0開始int m = a[k];cout << G.vertices[m] << "(" << D[m] << ")";if (k !=0) {cout << "->";}}cout << endl;} }
  • 結果參考
  • 結果:

查找和排序

折半查找法

套用以前的模板,不簡潔,但能用就行。

#include<iostream> using namespace std; //常量 #define MAXSIZE 1000 //數據元素類型約定為ElemType typedef int ElemType;int Searchcount = 0; //查找次數 //順序表的建立,定義了一個名為SqList的結構體 struct SqList {//當前長度int length;//存儲空間的基地址ElemType* elem; };//初始化順序表 int SqList_Init(SqList&); //順序表讀入值 void SqList_read(int, SqList&); //顯示菜單 void Menu(); void check_n(int n, SqList& L); //折半查找法 int Search1(SqList&, ElemType k); void Searchzheban(SqList&);int main() {int n;//初始化一個順序表SqList L;if (SqList_Init(L) == -2) {cout << "初始化失敗";return 0;}//給順序表賦值int m;//把m個元素放入順序表for (;;) {cout << "請輸入順序表的元素個數m:" << endl;cin >> m;if (m < 0) {cout << "請輸入合法的順序表的元素個數m:" << endl;}else break;}SqList_read(m, L);for (;;) {//顯示菜單Menu();//輸入操作碼for (;;) {cout << "請輸入操作代碼" << endl;cout << " 輸入負數退出" << endl;cin >> n;if (n ==1) {//根據操作碼選擇操作check_n(n, L);}else if (n < 0) {return 0;}else {cout << "請輸入正確操作碼" << endl;}}}return 0; }void Menu() {cout << endl;cout << "1812030065 李詩雨" << endl;cout << "1-------折半查找法" << endl; } void Status_check(int n) {if (n == 0) return;if (n == -2) return; } void check_n(int n, SqList& L) {//不要忘了每個case里都要breakswitch (n){case 1:Searchzheban(L);break;default:break;} } int SqList_Init(SqList& L) {//構造一個新的順序表L 并為之分配大小為MAXSIZE的空間L.elem = new ElemType[MAXSIZE];//關于elemtype...if (L.elem == NULL) {cout << "存儲空間分配失敗!" << endl;return -2;}L.length = 0;cout << "順序表初始化成功" << endl;return 1; } void SqList_read(int m, SqList& L) {for (int i = 0; i < m; i++) {ElemType e;cin >> e;L.elem[i] = e;L.length++;} }int Search1(SqList& L, ElemType k) {int low, high, mid;low = 0; high = L.length - 1;Searchcount = 0;while (low <= high){Searchcount++;mid = (low + high) / 2;if (k > L.elem[mid]){low = mid + 1;}else if (k == L.elem[mid]){return mid;}elsehigh = mid - 1;}return -1; } void Searchzheban(SqList& L) {cout << "請輸入要查找的元素:";ElemType k;cin >> k;int position = Search1(L, k);if (position == -1) {cout << "折半查找法: 查找失敗 ,查找次數為:" << Searchcount << endl;}else {cout << "折半查找法: " << k << " 的位置為:" << position << "查找次數為:" << Searchcount << endl;} }

二叉排序樹查找法

參考鏈接 二叉排序樹的構造和應用

#include<iostream> using namespace std; #define MAX 100 typedef struct TNODE {int data;int index;TNODE* lchild, * rchild; };void create(); void insert(int m,int i); //插入二叉排序樹的結點 void inOrder(TNODE* ptr); //中序遍歷 int searchCount = 0; int SearchBST2(TNODE* t, int k); void Search(TNODE* t);TNODE* root = NULL;int main() {cout << "1812030065 李詩雨" << endl;create();cout << endl;cout << " 按中序遍歷所得到的中序序列是一個遞增有序序列。" << endl;inOrder(root);cout << endl;for (;;) {int n;cout << "輸入0開始查找元素,輸入-1 結束程序" << endl;cin >> n;cout << endl;if (n == -1) {return 0;}Search(root);} } void inOrder(TNODE* ptr) {if (ptr != NULL){inOrder(ptr->lchild);cout << ptr->data<<" ";inOrder(ptr->rchild);} }void create() {int n, i;int k[MAX];cout << "請輸入元素結點個數:";cin >> n;cout << "輸入元素:";for (i = 0; i < n; i++){cin >> k[i];}for (i = 0; i < n; i++) {insert(k[i],i);} }void insert(int m,int i) {TNODE* p1, * p2;//如果二叉樹為空樹,創建根節點if (root == NULL){root = new TNODE;root->data = m;root->index = i;root->lchild = root->rchild = NULL;}else{p1 = root;while (m != p1->data){if ((m < p1->data) && (p1->lchild != NULL))p1 = p1->lchild;else if ((m > p1->data) && (p1->rchild != NULL))p1 = p1->rchild;else if ((m < p1->data) && (p1->lchild == NULL)){p2 = new TNODE;p2->data = m;p2->index = i;p2->lchild = p2->rchild = NULL;p1->lchild = p2;return;}else if ((m > p1->data) && (p1->rchild == NULL)){p2 = new TNODE;p2->data = m;p2->index = i;p2->lchild = p2->rchild = NULL;p1->rchild = p2;return;}}} }int SearchBST2(TNODE *t, int k) {searchCount = 0;TNODE* p = t;while (p != NULL && p->data != k){searchCount++;if (k < p->data)p = p->lchild;elsep = p->rchild;}searchCount++;//p == NULL 或 p->data == k 也算查找了一次if (p == NULL)return -1;elsereturn p->index; } void Search(TNODE* t) {cout << "二叉排序樹查找法: 請輸入要查找的元素:";int k;cin >> k;int position = SearchBST2(t, k);if (position == -1)cout << "查找失敗,查找次數為:" << searchCount << endl;elsecout<<"查找成功,元素 "<<k<<" 的位置是 "<<position<<" 查找次數為:" << searchCount << endl; }

折半查找插入法

#include<iostream> using namespace std; //常量 #define MAXSIZE 1000 //數據元素類型約定為ElemType typedef int ElemType;int Searchcount = 0; //查找次數 //順序表的建立,定義了一個名為SqList的結構體 struct SqList {//當前長度int length;//存儲空間的基地址ElemType* elem; };//初始化順序表 int SqList_Init(SqList&); //順序表讀入值 void SqList_read(int, SqList&); //顯示菜單 void Menu(); void check_n(int n, SqList& L); //折半插入排序 void BInsertSort(SqList& L);int main() {int n;//初始化一個順序表SqList L;if (SqList_Init(L) == -2) {cout << "初始化失敗";return 0;}//給順序表賦值int m;//把m個元素放入順序表for (;;) {cout << "請輸入順序表的元素個數m:" << endl;cin >> m;if (m < 0) {cout << "請輸入合法的順序表的元素個數m:" << endl;}else break;}SqList_read(m, L);for (;;) {//顯示菜單Menu();//輸入操作碼for (;;) {cout << "請輸入操作代碼" << endl;cout << " 輸入負數退出" << endl;cin >> n;if (n == 1) {//根據操作碼選擇操作check_n(n, L);}else if (n < 0) {return 0;}else {cout << "請輸入正確操作碼" << endl;}}}return 0; }void Menu() {cout << endl;cout << "1812030065 李詩雨" << endl;cout << "1-------折半插入排序" << endl; }void check_n(int n, SqList& L) {//不要忘了每個case里都要breakswitch (n){case 1:BInsertSort(L);break;default:break;} } int SqList_Init(SqList& L) {//構造一個新的順序表L 并為之分配大小為MAXSIZE的空間L.elem = new ElemType[MAXSIZE];//關于elemtype...if (L.elem == NULL) {cout << "存儲空間分配失敗!" << endl;return -2;}L.length = 0;cout << "順序表初始化成功" << endl;return 1; } void SqList_read(int m, SqList& L) {for (int i = 1; i <= m; i++) {ElemType e;cin >> e;L.elem[i] = e;L.length++;} }void BInsertSort(SqList& L) {int low, high, m;for (int i = 2; i <= L.length; ++i){L.elem[0] = L.elem[i];low = 1; high = i - 1;while (low <= high){m = (low + high) / 2;if (L.elem[0]< L.elem[m]) high = m - 1;else low = m + 1;}for (int j = i - 1; j >= high + 1; --j) L.elem[j + 1] = L.elem[j];L.elem[high + 1] = L.elem[0];}cout << "折半插入排序: ";for (int i = 1; i <= L.length; i++) {cout << L.elem[i] << " ";}cout << endl; }

冒泡排序

#include<iostream> using namespace std; //常量 #define MAXSIZE 1000 //數據元素類型約定為ElemType typedef int ElemType;int Searchcount = 0; //查找次數 //順序表的建立,定義了一個名為SqList的結構體 struct SqList {//當前長度int length;//存儲空間的基地址ElemType* elem; };//初始化順序表 int SqList_Init(SqList&); //順序表讀入值 void SqList_read(int, SqList&); //顯示菜單 void Menu(); void check_n(int n, SqList& L); //冒泡排序 void BubbleSort(SqList& L);int main() {int n;//初始化一個順序表SqList L;if (SqList_Init(L) == -2) {cout << "初始化失敗";return 0;}//給順序表賦值int m;//把m個元素放入順序表for (;;) {cout << "請輸入順序表的元素個數m:" << endl;cin >> m;if (m < 0) {cout << "請輸入合法的順序表的元素個數m:" << endl;}else break;}SqList_read(m, L);for (;;) {//顯示菜單Menu();//輸入操作碼for (;;) {cout << "請輸入操作代碼" << endl;cout << " 輸入負數退出" << endl;cin >> n;if (n == 1) {//根據操作碼選擇操作check_n(n, L);}else if (n < 0) {return 0;}else {cout << "請輸入正確操作碼" << endl;}}}return 0; }void Menu() {cout << endl;cout << "1812030065 李詩雨" << endl;cout << "1------- 冒泡排序" << endl; }void check_n(int n, SqList& L) {//不要忘了每個case里都要breakswitch (n){case 1:BubbleSort(L);break;default:break;} } int SqList_Init(SqList& L) {//構造一個新的順序表L 并為之分配大小為MAXSIZE的空間L.elem = new ElemType[MAXSIZE];//關于elemtype...if (L.elem == NULL) {cout << "存儲空間分配失敗!" << endl;return -2;}L.length = 0;cout << "順序表初始化成功" << endl;return 1; } void SqList_read(int m, SqList& L) {for (int i = 0; i < m; i++) {ElemType e;cin >> e;L.elem[i] = e;L.length++;} }void BubbleSort(SqList& L) {int j = L.length;while (j>1){int lastExchangeIndex = 0;for (int i = 1; i < j; i++) {if (L.elem[i] < L.elem[i - 1]) {int t = L.elem[i];L.elem[i] = L.elem[i - 1];L.elem[i - 1] = t;lastExchangeIndex = i;}}j = lastExchangeIndex;}cout << "冒泡排序: ";for (int i = 0; i < L.length; i++) {cout << L.elem[i] << " ";}cout << endl;}

總結

以上是生活随笔為你收集整理的数据结构(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。