数据结构总结

一:概述:

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

数据元素的关系。记作: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)为弧上的权值

                  <2> 若不存在,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 
 2 #include 
 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 
 2 #include 
 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 }

 

你可能感兴趣的:(数据结构总结)