数据结构总结

匿名 (未验证) 提交于 2019-12-03 00:13:02

一:概述:

数据结构:是计算机存储和组织数据的方式,是相互间存在着一种或多种关系的数据元素的集合和该集合中

数据元素的关系。记作:Data_Structure(D,R)

D:是数据元素的集合   R:是该集合中所有元素之间的关系的有限集合。

二:数据结构的研究对象

(一)数据的逻辑结构: 反应数据元素之间的前后件关系,与计算机的存储位置无关。

         1)集合:数据结构中的元素之间除了"同属一个集合”的相互关系外,别无其余关系。

         2)线性结构:数据结构中的元素存在 一对一 的关系。

         3)树形结构:数据结构中的元素存在 一对多 的关系。

         4)图结构:数据结构中的元素存在  多对多 的关系。

(二) 数据的物理结构: 是指数据在计算机存储空间的存放形式,一种逻辑结构可以表示成多种存储结构。

(三)数据结构的运算:

(1)Creat: 建立一个数据结构

(2)Destroy:消除一个数据结构

(3)Delete:从一个数据结构中删除一个数据元素

(4)Insert:把一个数据元素插入到一个数据结构中

(5)Access:对一个数据结构进行访问

(6)Modify:对一个数据结构中的数据元素进行修改

(7)Sort:对一个数据元素中的数据元素进行排序

(8)Search:对一个数据元素中数据元素进行查找

三:线性表:a[ 0 ... n] 构成的一个表,长度为 n, 若 n=0,该表是空表

1)当 i = 1 ..... n-1, a[ i ] 有且仅有一个直接前驱 a[ i -1 ]。

2)当 i = 0 ..... n-2, a[ i ] 有且仅有一个直接后继a[ i + 1 ]。

3)第一个元素没有前驱。

4)最后一个元素没有后继。

四:栈与队列

(1) 栈:遵循先进后出的原则,只允许在栈顶对元素进行插入和删除的操作,另一端就是栈底。

(2) 队列:先进先出表  当 front == rear 表示队空

                队头 ( front ) 进行删除操作 , 队尾 ( rear ) 端进行删除操作。

五:二叉树:一种有限元素的集合,该集合或者为空,或者由一个称为 根 的元素及两个不相交的

       左子树和右子树组成。

(1) 先序遍历:

1 void PreOrderTraverse(BNode *p) 2 { 3     if(p!=NULL)   //若二叉树为空,则空操作 4     { 5         printf("%c*",p->data);   //访问根节点 6         PreOrderTraverse(p->lchild);  //先序遍历左子树 7         PreOrderTraverse(p->rchild);  //先序遍历右子树 8     } 9 }

(2)中序遍历:

1 void InOrderTraverse(BNode *p) 2 { 3     if(p!=NULL) 4     { 5         InOrderTraverse(p->lchild);  //中序遍历左子树 6         printf("%c*",p->data);       //访问根节点 7         InOrderTraverse(P->rchild);   //中序遍历右子树 8     } 9 }

(3)后序遍历:

void PostOrderTraverse(BNode *p) {     if(p!=NULL)     {         PostOrderTraverse(p->lchild);   //后序遍历左子树         PostOrderTraverse(p->rchild);   //后序遍历右子树         printf("%c*",p->data);        //访问根节点     } }

(六)图:

图的遍历:从图中的某个顶点出发访遍图中其余顶点且仅访问一次的过程。

(1)深度优先遍历:从图中某个点出发,然后访问完图中与这个点路径相通的点, 若图中还有未被

访问的点,从未被访问的点开始重复上述步骤。(一条道走到黑)

1 void DFS(Graph G, int v) 2 {//从顶点 v 出发递归地深度优先遍历图 G 3     visited[v] = TRUE; Visit(v);   //访问顶点 v 4     for(w = FirstAdjVex(G,v); w; w = NextAjVex(G,V,W)) 5         if(!visited[w]) DFS(G,w);   //对 v 的尚未访问的邻接顶点 w 递归地深度优先遍历 6 }

(2)广度优先遍历:从图中某个点出发,然后先访问完图中与这个点路径相通最近的点,然后再从这些最

近的点访问与这些点最近的子节点,若图中还有未被访问的点,从未被访问的点开始重复上述步骤。(分身术)

 1 void BFSTraverse(Graph G, Status(*Visited)(int v))  2 {//按广度优先递归遍历图 G 使用辅助队列 Q 和访问标志数组 visited  3     for(v = 0; v < G, vexnum; ++v)    4         Visited[v] = FALSE;  5     InitQueue(Q);            //置空 队列 Q  6     if(!visited[v])         //尚未访问  7     {                      8         EnQueue(Q,v);       //v 入队列     9         while(!QueueEmpty(Q))  10         { 11             DeQueue(Q,u);          //队头元素出队并置为u 12             Visited[u] = FALSE;visit(u);  //访问 u 13             for(w = FirstAdjVex(G,u); w; w = NextAdjVex(G,u,w)) 14                 if(!Visited[w]) EnQueue(Q,w);  //u 的尚未访问的邻接点 w 入队列 Q 15         } 16     } 17 }

七:最短路径:源点与终点之间经过的边上权值之和最小的路径。

(1)Dijkstra(没有负权的单源最短路径)

                  步骤一:初始化时令 S = { v0 }, T = V - S ={ 其余顶点 },S 代表已经走过的顶点,设d(v,u)

代表顶点 v 到 u 的边权值。

                  <1> 若存在 < v0, vi>,d(v0,vi)为<v0,vi>弧上的权值

                  <2> 若不存在<v0,vi>,d(v0,vi)为 ∞

                  步骤二:从 T 中选取一个与 S 中顶点有关联边且权值小的顶点 w,加入到 S 中。

                  步骤三:对 T 中其余顶点的距离值进行修改

                                           d(v0,vi) = min(d(v0,vi),d(v0,w)+d(w,vi))

                  若加进 w 作中间顶点,从 v0 到 vi 的距离值缩短,则修改此距离。

                  步骤四:重复上述步骤 2、3,直到 S 中 包含所有顶点,即 w = vi 为止。         

 1 #include <iostream>  2 #include <cstdio>  3 #define MAX 1000000  4 using namespace std;  5 int arcs[10][10];  //邻接矩阵  6 int D[10];         //保存最短路径长度  7 int p[10][10];     //路径  8 int final[10];    //若final[i] = 1; 则说明 v[i] 已在集合 S中  9 int n = 0;        //顶点个数 10 int v0 = 0;      //顶点 11 int v,w; 12 void Dijkstra() 13 { 14     for(v = 0; v < n; v++)    //循环初始化 15     { 16         final[v] = 0; D[v] = arcs[v0][v]; 17         for(w = 0; w < n; w++) p[v][w] = 0;   //设空路径 18         if(D[v] < MAX) 19         { 20             p[v][v0] = 1; 21             p[v][v] = 1; 22         } 23     } 24     D[v0] = 0; final[v0] = 0;    //初始化 v0 顶点属于集合 S 25     //开始1主循环,每次求得 v0 到某个顶点 v 的最短路径,并将 v 加到 集合 S 中 26     for(int i = 1; i < n; i++) 27     { 28         int min = MAX; 29         for(w = 0; w < n; w++) 30         { 31             if(!final[w])    //如果顶点 w 在 v - s 中 32             { 33                 if(D[w] < min) 34                 { //这个过程最终选出的点应当是当前 v-s 中与 s 有关联边且权值最小的顶点 35                     v = w; 36                     min = D[w]; 37                 } 38             } 39         } 40         final[v] = 1;   //选出该点后加入到集合 s 中 41         for(w = 0; w < n; w++)   //更新当前最短路径和距离 42         { 43             /*** 44             在此循环中, v 为当前刚选入集合 s 中的点,则以 v 为中间点 考察 d(v0,v) + d(v,w) 45             是否小于D[w],如果是,则更新。 46             ***/ 47             if(!final[w] && (min + arcs[v][w] < D[w])) 48             { 49                 D[w] = min + arcs[v][w]; 50                 p[w][w] = 1; 51             } 52         } 53     } 54 } 55  56 int main() 57 { 58     cin>>n; 59     for(int i = 0; i < n; i++) 60         for(int j = 0; j < n; j++) 61             cin>>arcs[i][j]; 62  63     Dijkstra(); 64     for(int i = 0; i < n; i++) 65         printf("D[%d]=%d\n",i,D[i]); 66     return 0; 67 }

 

(2)Floyed( 多源最短路径)

                步骤一:初始化最短路径。两点之间的距离时边的权,如果两点之间没有边相连,则权为无穷大。

                步骤二:对于没一对顶点 u,v ,检查是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。

如果是,则更新最短路径。

                步骤三:把图用邻接矩阵 G 表示出来。如果 vi 到 vj 有路可达,则G[ i ][ j ] = d, d 表示该路的长度;

否则G[ i ][ j ] = 无穷大。 定义一个 矩阵 D 用来记录所插入点的信息,D[ i ][ j ] 表示从 vi 到 vj 需要经过路上的

点,初始化 D[ i ][ j ] = j。把各个顶点插入 图中,比较插入顶点后 的距离 与原来的距离,     G[ i ][ j ] = min

(G[ i ][ j ],G[ i ][ k ] + G[ k ][ j ]),如果 G[ i ][ j ] 的值变小,则更新D[ i ][ j ] = k。在 G 中包含两点之间的最短路径

的长度,在D中包含两点之间最短路径经过的点。

 1 #include <iostream>  2 #include <cstdio>  3 #define max 1000000000  4 using namespace std;  5 int d[1000][1000], path[1000][1000];  6 int main()  7 {  8     int i,j,k,m,n;  9     int x,y,z; 10     scanf("%d%d",&n,&m); 11     for(i = 1; i <= n; i++) 12     { 13         for(j = 1; j <= n; j++) 14         { 15             d[i][j] = max; 16             path[i][j] = j; 17         } 18     } 19     for(i = 1; i <= m; i++) 20     { 21         scanf("%d%d%d",&x,&y,&z); 22         d[x][y] = z; 23         d[y][x] = z; 24     } 25     for(k = 1; k <= n; k++) 26         for(i = 1; i <= n; i++) 27             for(j = 1; j <= n; j++) 28             { 29                 if(d[i][k] + d[k][j] < d[i][j]) 30                 { 31                     d[i][j] = d[i][k] + d[k][j]; 32                     path[i][j] = path[i][k]; 33                 } 34             } 35     for(i = 1; i <= n; i++) 36         for(j = 1; j <= n; j++) 37             if(i != j) printf("%d->%d:%d\n",i,j,d[i][j]); 38     int st,en; 39     scanf("%d%d",&st,&en); 40     while(st != en) 41     { 42         printf("%d->",st); 43         st = path[st][en]; 44     } 45     printf("%d\n",en); 46     return 0; 47 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!