目录

线性表

一、顺序存储

1.顺序存储的静态分配

2.顺序存储的动态分配

3.顺序存储线性表的插入

4.顺序存储线性表的删除

二、链式存储

5.链式存储线性表的结构

6.头插法建立单链表

7.尾插法建立单链表

8.链式存储按序号查找结点

9.链式存储按值查找结点

10.链式存储插入结点

11.链式存储删除结点

12.双链表的结构

13.双链表的插入

14.双链表的删除

15.静态链表的结构

栈和队列

一、顺序栈

16.栈的结构

17.判断栈空

18.进栈

19.出栈

20.读取栈顶元素

21.共享栈的结构

22.共享栈的进栈

二、链式栈

23.链式栈的存储结构

24.链式栈的进栈

25.链式栈的出栈

三、顺序队列

26.队列的存储结构

27.队列的入队

28.队列的出队

四、链式队列

29.链式队列的存储结构

30.链式队列的入队

31.链式队列的出队

五、栈的应用

32.栈的应用:括号匹配

34.栈的应用:求斐波那契数列的第n项

树和二叉树

一、树的存储结构

35.树的双亲表示法

36.树的孩子表示法

37.孩子兄弟表示法

38.二叉树的链式存储

二、树的遍历

39.二叉树的递归先序遍历

40.二叉树的递归中序遍历

41.二叉树的递归后序遍历

42.二叉树的非递归先序遍历

43.二叉树的非递归中序遍历

44.二叉树的非递归后序遍历

45.二叉树的层序遍历

三、线索二叉树

46.线索二叉树的结构

47.中序遍历对二叉树线索化的递归算法

48.遍历线索二叉树

一、图的存储结构

49.图的邻接矩阵存储

50.图的邻接表存储

二、图的遍历

51.图的广度优先搜索遍历(BFS)

52.BFS应用:单源非带权图最短路径

53.图的深度优先遍历(DFS)

三、图的最小生成树

54.求图的最小生成树(Prim算法)

55.并查集:查找某个集合的根结点(Kruskal算法用到)

56.并查集:合并两个集合(Kruskal算法用到)

57.求图的最小生成树:(Kruskal算法)克鲁斯卡尔

四、图的最短路径

58.图的最短路径算法(Dijkstra算法)迪杰斯特拉

59.图的最短路径算法(Floyd算法)弗洛伊德

查找

60.折半查找

61.二叉排序树查找关键字(递归)

62.二叉排序树查找关键字(非递归)

63.二叉排序树插入关键字

64.二叉排序树构造代码

排序

65.直接插入排序

66.希尔排序

67.冒泡排序

68.快速排序

69.选择排序

70.堆排序

71.归并排序

73.拓扑排序


线性表

一、顺序存储

1.顺序存储的静态分配

#define MaxSize 50//定义线性表的最大长度
typedef int Elemtype//假定表中元素类型是int
typedef struct{ElemType data[MaxSize];//顺序表的元素(数组)int length ;//顺序表的当前长度

2.顺序存储的动态分配

typedef int Elemtype
typedef struct
{ElemType *data ;//指示动态分配数组的指针 int MaxSize , length ;//数组的最大容量和当前个数
};/* c语言的动态分配语句 */
#define InitSize 100
SeqList L;
L.data=(ElemType*)malloc(sizeof(ElemType)*InitSzie);

3.顺序存储线性表的插入

bool ListInset(Sqlist &L, int i , ElemType e){if(i<1 || i>L.length+1)  return false ;//判断i的范围是否有效 if(L.length >= MaxSize)  return false ;//当前存储空间已满,不能插入 for(int j=L.length ; j>=i ; j--){//将第i个元素及之后的元素后移L.data[j]=L.data[j-1];}L.data[i-1] = e ;//在位置i处放入e L.length++ ; //线性表长度加1 return true ;
}

4.顺序存储线性表的删除

bool ListDelete(SqList &L , int i ,Elemtype &e){if(i<1 || i>=L.length) return false;//判断i的范围是否有效 e = L.data[i];//将被删除的元素赋值给e for(int j=i ; j<=L.length ; j++){//将第i个位置之后的元素前移 L.data[j]=L.data[j+1] ;}L.length--; //线性表长度减1 return true ;
}

二、链式存储

5.链式存储线性表的结构

typedef struct LNode //定义单链表结点类型
{ElemType data ;//数据域 struct LNode *next; //指针域
}LNode, *LinkList;

6.头插法建立单链表

LinkList CreatLinkList(LinkList &L){LNode *s ; //辅助指针 int x ;L=(LinkList)malloc(sizeof(LNode)) ; //创建头结点 L->next = NULL ;//初始为空链表 scanf("%d" , &x) ;//输入结点的值 while(x != 9999){//输入9999表示结束 s= (LNode*)malloc(sizeof(LNode)); //创建新结点 s->data = x ;s->next = L->next ;L->next = s ;//将新结点插入表中,L为头指针 scanf("%d" , &x) ;//读入下一个结点值}return L;
}

7.尾插法建立单链表

LinkList CreatLinkList(LinkList &L){int x ;L=(LinkList)malloc(sizeof(LNode));LNode *s , *r = L; //r为表尾指针 指向表尾 scanf("%d" , x) ; //输入结点的值 while(x != 9999){//输入9999表示结束 s=(LNode*)malloc(sizeof(LNode)) ;s->data = x ;r->next = s ;r= s ;//r指向新的表尾结点 scanf("%d" , x) ;}r->next = NULL ;//尾结点指针置空 return L;
}

8.链式存储按序号查找结点

LNode * GetElem(LInkList L , int i){int j = 1;//计数,初始为1 LNode *p = L->next ;//第一个结点指针赋给pif(i==0) return L ;//若i等于0,则返回头结点 if(i<1) return NULL; //若i无效,则返回NULL while (p && j<i){ //从第1个结点开始找,查找第i个结点 p=p->next ;j++;}return p; //返回第i个结点的指针,如果i大于表长,直接返回p即可}

9.链式存储按值查找结点

LNode * LocateElem(LinkList L, ElemType e){LNode *p = L->next;while(p!=NULL && p->data!=e){//从第1个结点开始查找data域为e的结点 p = p->next ;}return p;//找到后返回该结点指针,否则返回NULL
}

10.链式存储插入结点

算法思路: 1.取指向插入位置的前驱结点的指针       ① p=GetElem(L,i-1); 2.令新结点*s的指针域指向*p的后继结点  ② s->next=p->next; 3.令结点*p的指针域指向新插入的结点*s ③ p->next=s;
bool LinkListInsert(LInkList &L , int i ,ElemType e){if( i<1 || i>=L.length) return false ;int j = 1;LNode *p = L->next , *s;s = (LNode*)malloc(sizeof(LNode));while (p && j<i-1){p=p->next ;j++;}s->next = p->next;p->next = s ;return true ;
}

11.链式存储删除结点

算法思路:  1.取指向删除位置的前驱结点的指针  p=GetElem(L,i-1);2.取指向删除位置的指针              q=p->next;3.p指向结点的后继指向被删除结点的后继  p->next=q->next4.释放删除结点              free(q);
bool LinkListDelete(LInkList &L , int i ,ElemType &e){if( i<1 || i>=L.length) return false ;int j = 1;LNode *p = L->next ,*q ;while (p && j<i-1){p=p->next ;j++;}q = p->next ;  p->next = q->next;e = q->data;free(q) ;return true ;
}

12.双链表的结构

typedef struct DNode //定义单链表结点类型
{ElemType data ; //数据域 struct DNode *prior ,*next ;//前驱和后继指针
}DNode ,*DLinkList;

13.双链表的插入

bool DLinListInsert(DLInkList &L , int i ,ElemType e){if( i<1 || i>=L.length) return false ;int j = 1;DNode *p = L->next , *s;s = (DNode*)malloc(sizeof(DNode));while (p && j<i-1){p=p->next ;j++;}s->next = p->next;p->next->prior = s ;s->prior = p ;p->next = s;return true ;
}

14.双链表的删除

bool DLinkListDelete(DLinkList &L , int i ,ElemType &e){if( i<1 || i>=L.length) return false ;int j = 1;DNode *p = L->next ,*q ;while (p && j<i-1){p=p->next ;j++;}q = p->next ;p ->next = q->next ;q ->next->prior = p;e = q->data;free(q) ;return true ;
}

15.静态链表的结构

#define MaxSize 50   //静态链表的最大长度
typedef int ElemType //静态链表的数据类型假定为int
typedef struct  //静态链表结构类型的定义
{ElemType data ; //数据域:存储数据元素 int next ;//指针域:下一个元素的数组下标
}SLinkList[MaxSize];

栈和队列

一、顺序栈

16.栈的结构

#define MaxSize 50 //定义栈中元素的最大个数
typedef struct
{ElemType data[MaxSize] ;//存放栈中元素 int top ;//栈顶指针
}SqStack; //顺序栈的简写

17.判断栈空

bool StackEmpty(SqStack S){if(s.top == -1) return true ;else return false ;
}

18.进栈

bool Push(SqStack &S , ElemType x){if(S.top == MaxSize-1) return false ;S.data[++top] = x ; return true ;
}

19.出栈

bool Pop(SqStack &S,ElemType &x) {if(S.top == -1) return false ;x = S.data[top--] ;return true ;
}

20.读取栈顶元素

bool Pop(SqStack &S,ElemType &x) {if(S.top == -1) return false ;x = S.data[top] ;return true ;
}

21.共享栈的结构

#define MaxSize 100  //定义栈中元素的最大个数
typedef struct
{ElemType data[MaxSize] ;//存放栈中元素 int top1 ;//栈1栈顶指针 int top2 ;//栈2栈顶指针
}SqDoubleStack;  //顺序共享栈的简写

22.共享栈的进栈

bool Push(SqDoubleStack &S , ElemType x , int stackNum){if(S.top1+1 == S.top2) return false ; //栈满 if(stackNum == 1) //栈1有元素进栈S.data[++top1] = x;else(stackNum == 2)//栈2有元素进栈 S.data[--top2] = x;return true ;
}

二、链式栈

23.链式栈的存储结构

typedef struct SNode
{ElemType data ;//存放栈中元素 struct SNode *next ; //栈顶指针
}SNode , *SLink; //链栈的结点
typedef struct LinkStack
{Slink top ; //栈顶指针 int count ; //链栈结点数
}LinkStack; //链栈

24.链式栈的进栈

bool Push(LinkStck &S, ElemType x){SLink p = (Slink)malloc(sizeof(SNode)) ; //给新元素分配空间 p->data = x ;//新元素的值 p->next = S->top ;  //p的后继指向栈顶元素 S->top = p ;   //栈顶指针指向新的元素 S->count++ ;   //栈中元素个数加1 return true ;
}

25.链式栈的出栈

bool Pop(LinkStack *S , ElemType &x) {if(S->top == NULL) return false ;x = S->top->data ;  //栈顶元素值 Slink p = S->top ; //辅助指针 S->top = S->top->next ;   //栈顶指针后移free(p); //释放被删除数据的存储空间 S->count-- ;//栈中元素个数减一 return true ;
}

三、顺序队列

26.队列的存储结构

#define MaxSize 50//定义队列中元素的最大个数
typedef struct
{ElemType data[MaxSize] ;//存放队列元素 int front ,rear ;//队头指针和队尾指针
}SqQueue;

27.队列的入队

bool EnQueue(SqQueue &Q , ElemType x){if((Q.rear+1)%MaxSize == Q.front ) return false ;//队满Q.data[Q.rear] = x;Q.rear = (Q.rear+1)%MaxSize ;return true ;
}

28.队列的出队

bool DeQueue(SqQueue &Q ,ElemType &x){if(Q.front == Q.rear) return false ; //队空,报错 x = Q.data[Q.front] ;Q.front = (Q.front+1)%MaxSize ;return true ;
}

四、链式队列

29.链式队列的存储结构

typedef struct //链式队列结点
{ElemType data ;struct LinkNode *next ;
}LinkNode;
typedef struct //链式队列
{LinkNode *front,*rear ;   //队头和队尾指针
}LinkQueue;

30.链式队列的入队

void EnQueue(LinkQueue &Q, ElemType x){s=(LinkNode *)malloc(sizeof(LinkNode)) ;s->data = x ;s->next = NULL ;Q.rear->next = s ;Q.rear = s ;
}

31.链式队列的出队

bool DeQueue(LinkQueue &Q , ElemType &x){if(Q.rear == Q.front ) return false ; //空队 p = Q.front->next ;x = p->data ;Q.front->next = p->next ;if(Q.rear == p) //若原队列中只有一个结点,删除后变空 Q.rear = Q.front ;free(p) ;return true ;
}

五、栈的应用

32.栈的应用:括号匹配

bool Check(char *str){Stack s ;InitStck(s) ;int len = strlen(str) ; //字符串长度为len for (int i = 0; i<len ; i++){char a = str[i] ;swith(a){case '(':case '[':case '{'Push(s,a) ;break ;case ')':if(Pop(s) != '(' ) return false ; //出栈顶。如果不匹配直接返回不合法 break ;case ']':if(Pop(s) != '[' ) return false ;break ;case '}':if(Pop(s) != '{' ) return false ;break ;}}if(Empty(s)) return true ;//匹配完所有括号最后要求栈中为空 else return false ;
}

34.栈的应用:求斐波那契数列的第n项

int Fib(int n){if( n== 0 ) return 0 ;  //1.递归边界 Fib(0)==0, Fib(1)==1 else if(n == 1) return 1 ; //2.递归式 Fib(n)=Fib(n-1)+Fib(n-2) else return Fib(n-1)+Fib(n-2) ;
}

树和二叉树

一、树的存储结构

35.树的双亲表示法

typedef char ElemType ;
typedef struct TNode
{ElemType data ;  //结点数据 int parent ; //该结点双亲在数组中的下标
}TNode; //结点数据类型
#define MaxSize 100
typedef struct
{TNode nodes[MaxSize] ; //结点数组 int n;  //结点数量
}Tree;//树的双亲表示结构

36.树的孩子表示法

typedef char ElemType ;
typedef struct CNode
{int chlid ;//该孩子在表头数组的下标struct CNode *Next ; //指向该结点的下一个孩子结点
}CNode ,*child ;//孩子结点数据类型typedef struct
{ElemType data ;  //结点数据域 child firstchild ;//指向该结点的第一个孩子结点
}TNode ;//孩子结点数据类型#define MaxSize 100
typedef struct
{TNode nodes[MaxSize] ;//结点数据域 int n ;//树中结点个数
}tree;  //树的孩子表示结构

37.孩子兄弟表示法

typedef char ElemType ;
typedef struct CSNode
{ElemType data ;//该结点的数据域 struct CSNode *firstchild ,*rightchild ; //指向该结点的第一个孩子结点和该结点的右兄弟结点
}CSNode ; //孩子兄弟结点数据类型

38.二叉树的链式存储

typedef struct BiTNode
{ElemType data ;//数据域struct BiTNode *lchild ,*rchild ; //指向该结点的左、右孩子指针
}BiTNode , *BiTree ;  //二叉树结点结构

二、树的遍历

39.二叉树的递归先序遍历

void PreOrder(BiTree T){if(T != NULL) {print ("%c" , T->data) ; //访问根结点 PreOrder(T->lchild) ;//递归遍历左子树 PreOrder(T->rchild) ;   //递归遍历右子树}
}

40.二叉树的递归中序遍历

void InOrder(BiTree T){if(T != NULL){InOrder(T->lchild) ;//递归遍历左子树 print("%c" , T->data) ;//访问根结点 InOrder(T->rchild) ;  //递归遍历右子树}
}

41.二叉树的递归后序遍历

void PostOrder(BiTree T){if(T != NULL){PostOrder(T->lchild) ;//递归遍历左子树 PostOrder(T->rchild) ;  //递归遍历右子树print("%c" , T->data) ;//访问根结点 }
}

42.二叉树的非递归先序遍历

void PreOrderTraverse(BiTree b){Stack s ;InitStack(s) ;BiTree p = b ;  //工作指针p while(p || !IsEmpty){while(p){printf("%c", p->data) ; //先序先遍历结点 Push(S,p);p= p->lchild ;}if(!IsEmpty(S)){p=Pop(s) ;p= p->rchild ;}}
}

43.二叉树的非递归中序遍历

void InOrderTraverse(BiTree b){Stack s;InitStack(s) ;BiTree p = b ;  //工作指针p while (p || !IsEmpty(s)){while(p){//中序先将结点进栈保存 Push(s,p) ;p = p->lchild ;}//遍历到左下角尽头再出栈访问 p = Pop(s) ;printf("%c" , p->data) ;p = p->rchild ;//遍历右孩子}
}

44.二叉树的非递归后序遍历

void PostOrderTraverse(BiTree T){InitStack(S) ;BiTree p = b , r = NULL ;//工作指针p  辅助指针r while(p || !IsEmpty(s)){//1.从根结点到最左下角的左子树都入栈 if(p){Push(S,p) ;p=p->lchild ;}//2.返回栈顶的两种情况 else{GetTop(S,p) ;//取栈顶注意不是出栈! //①右子树还未访问,而且右子树不空,第一次栈顶 if(p->rchild && p->rchild!=r) p = p->rchild ;//②右子树已经访问或为空,接下来出栈访问结点 else{Pop(S,p);printf("%c" , p->data) ;r = p ; //指向访问过的右子树根结点 p = NULL ;//使p为空从而继续访问栈顶}}}
}

45.二叉树的层序遍历

void LevelOrder(BiTree T){InitQueue(Q) ;BiTree p ;EnQueue(Q , b) ; //根结点进队while (!IsEmpty(Q))//队列不空循环 {DeQueue(Q , p); //队头元素出队 printf("%c" , p->data) ;if(p->lchild != NULL) EnQueue(Q,p->lchild) ;if(p->rchild != NULL)EnQueue(Q,p->rchild) ;}
}

三、线索二叉树

46.线索二叉树的结构

typedef struct ThreadNode
{ElemType data ;struct ThreadNode *lchild , *rchild ;int ltag ,rtag ;
}ThreadNode ,*ThredTree;//线索链表

47.中序遍历对二叉树线索化的递归算法

void InThread(ThreadTree &p ,ThreadTree &pre){if(p){//pre指向中序遍历时上一个刚刚访问过的结点 初值为NULInThread(p->lchild , pre) ;if(p->lchild == NULL){p->lchild = pre ;p->ltag = 1 ;}if(pre!=NULL && pre->rchild==NULL){pre->rchild = p ;p->rtag = 1 ;}pre = p ;InThread(p->rchild,pre) ;}
}

48.遍历线索二叉树

void InOrderTraverse(ThreadTree T){ThredTree p = T ;while(p){while(p->ltag == 0){p = p->lchild ;printf("%c", p->data) ;}  while(p->rtag==1 && p->rchild){p=p->rchild ;printf("%c", p->data) ;}p = p->rchild ;    }
}

一、图的存储结构

49.图的邻接矩阵存储

#define MaxVertexNum 100//顶点数目的最大值
typedef char VertexType ;//顶点的数据类型 不同情况不一样
typedef int EdgeType ;//整数表示权值或者连通性
typedef struct
{VertexType Vex[MaxVertexNum];//顶点表EdgeType Edge[MaxVertexNum][MaxVertexNum] ;//邻接矩阵(二维数组),边表int vexnum , arcnum ;//图的当前顶点数和弧数
}MGraph;

50.图的邻接表存储

typedef struct VNode//顶点表结点
{VertexType data ;//顶点信息ArcNode *firstedge ;//单链表头指针
}VNode,AdjList[MaxVertexNum];//AdjList是结构体数组类型#define MaxVertexNum 100//图中顶点数目的最大值
typedef struct ArcNode//边表结点
{int adjvex ;//该弧所指向的顶点的位置struct ArcNode *next ;//指向下一条弧的指针
}ArcNode;typedef struct
{AdjList vertices ;//邻接表int vexnum ,arcnum ;//图的顶点数和弧数
}ALGraph;//ALGraph是以邻接表存储的图类型

二、图的遍历

51.图的广度优先搜索遍历(BFS)

#define MaxSize 100
bool visited[MaxSize] ;
void BFS(Graph G ,int v){ArcNode *p ;//工作指针pInitQueue(Q) ;//初始化一个队列visited(v) ;//访问第一个顶点v,具体可以是printvisited[v] = TRUE ;//对v做已访问标记while(!IsEmpty(Q)){//只要队列不为空DeQueue(Q,v) ;//顶点v出队列p = G->adjList[v].firstedge ;//指针p指向当前顶点的边表链表头指针while(p){if(!visited[p->adjvex]){//p指向顶点如果未被访问visited(p->adjvex) ;//访问p所指向的顶点visited[p->adjvex] = TRUE ;//对这个顶点做已访问标记EnQueue(Q, p->adjvex) ;//这个顶点入队列}p=p->next ;//p指向该顶点的下一条边}}
}void BFSTraverse(Graph G){int i ;//单独定义是为了方便多个循环中使用for (i=0;i<G->vexnum ; i++){visited[i] = false ;//将标志数组初始化(全局数组)}for (i=0;i<G->vexnum ; i++){if(!visited[i]) BFS(G,i);//为了避免非连通图的一些顶点访问不到,若是连通图只会执行一次}
}

52.BFS应用:单源非带权图最短路径

void BFS_MIN_Distance(Graph G, int u){for(i=0;i<G.vexnum;++i) d[i] = ∞ ;//d[i]表示从u到i结点的最短路径visited[u] = TRUE ;d[u] = 0 ;EnQueue(Q,u) ;while(!IsEmpty(Q)){DeQueue(Q,u) ;ArcNode *p = G->adjList[u].firstedge;while(p){if(!visited[p->adjvex]){visited[p->adjvex] = TRUE ;d[p->adjvex] = d[u]+1 ;//路径长度加1EnQueue(Q,p->adjvex) ;}p=p->next; }}
}

53.图的深度优先遍历(DFS)

#define MaxSize 100
bool visited[MaxSize] ;void DFS(Graph G, int v){ArcNode *p ;//工作指针pvisit(v);//访问顶底v(一般是打印,printf)visited[v] = TRUE ;//修改访问标记p = G->adjList[v].firstarc;//指针p开始指向该顶点的第一条边while(p!=NULL){//没遍历完顶点的所有邻接顶点if(!visited[p->adjvex]){//如果该顶点没被访问DFS(G,p->adjvex);//递归访问该顶点}p=p->nextarc ;//看还有没有其他未访问的顶点}
}
void DFSTraverse(Graph G){int i ;//单独定义是为了方便多个循环中使用for (i=0;i<G->vexnum ; i++){visited[i] = false ;//将标志数组初始化 (全局数组)}for (i=0;i<G->vexnum ; i++){if(!visited[i]) DFS(G,i);//对所有}
}

三、图的最小生成树

54.求图的最小生成树(Prim算法)

void MiniSpanTree_Prim(MGraph G){int min ,i ,j ,k ;int adjvex[MAXVEX] ;//保存邻接顶点下标的数组int lowcost[MAXVEX] ;//记录当前生成树到剩余顶点的最小权值lowcost[0] = 0 ;//将0号顶点(以0号顶点作为第一个顶点)加入生成树adjvex[0] = 0 ;//由于刚开始生成树只有一个顶点 不存在边 干脆都设为0for(i=0 ;i<G.vexnum ;i++){//除下标为0以外的所有顶点lowcost[i] = G.arc[0][i];//将与下标为0的顶点有边的权值存入Lowcost数组adjvex[i] = 0 ;//这些顶点的adjvex数组全部初始化为0}for(i=1;i<G.vexnum;i++){//只需要循环N-1次,N为顶点数min = 65535 ;//tip:因为要找最小值,不妨先设取一个最大的值来比较j = 0 ;k = 0 ;//找出lowcost最小的 最小权值给min,下标给kwhile(j<G.vexnum){//从1号顶点开始找if(lowcost[j]!=0 && lowcost<min){//不在生成树中的顶点而且权值更小的min = lowcost[j] ;//更新更小的值k = j ;//找到了新的点下标给k}j++ ;//再看下一个顶点}printf("(%d->%d)",adjvex[k],k;//打印权值最小的边lowcost[k] = 0 ;//将这个顶点加入生成树//生成树加入了新的顶点 从下标为1的顶点开始更新lowcost数组值for(j=0;j<G.vexnum;j++){if(lowcost[j]!= && G.arc[k][j]<lowcost[j]){//如果新加入树的顶点k使得权值变小lowcost[j] = G.arc[k][j] ;//更新更小的权值adjvex[j] = k ;//修改这条边邻接的顶点 也就是表示这条边是从选出的顶点k指过来的  方便打印     }}}
}

55.并查集:查找某个集合的根结点(Kruskal算法用到)

int Find(int *parent, int x){while (parent[x]>=0) x=parent[x];//循环寻找x的根return x ;//根的parent小于0
}

56.并查集:合并两个集合(Kruskal算法用到)

void Union(inbt *parent,int root1 ,int root2){parent[root2] = root1 ;
}

57.求图的最小生成树:(Kruskal算法)克鲁斯卡尔

#define 100
typedef struct
{int a,b ;//边的两个顶点int weight ;//边的权值
}Edge;//边的结构体
int Find(int *parent, int x){while (parent[x]>=0) x=parent[x];//循环向上寻找下表为x顶点的根return x ;//while循环结束时找到了根的下标
}
Edge edges[MaxEdge] ;//边数组
int parent[MaxVex] ;//父亲顶点数组(并查集)
void MiniSpanTree_Kruskal(MGraph G){int i,n,m ;sort(edges) ;//按权值由小到大对边排列for (int i=0;i<G.vexnum;i++){parent[i] = -1 ;//初始化:各个顶点单独形成一个集合}for(i=0;i<arcnum;i++){//扫描每条边n = Find(parent,edges[i].a) ;//n是这条边的第一个顶点的根顶点所在下标m = Find(parent,edges[i].b) ;//m是这条边第二个顶点的根顶点所在下标if(n!=m){//根顶点不相同 这条边不会构成环parent[n] = m ;//并操作printf("(%d->%d)",edges[i].a,edges[i].b);//作为生成树的一条边打印出来}}
}

四、图的最短路径

58.图的最短路径算法(Dijkstra算法)迪杰斯特拉

void Dijkstra(MGraph G,int v,int path[],int dist[]){ //v是源点的下标 int s[maxSize]; //数组s记录当前找到了到哪些顶点的最短路径 找到了对应值为1 没找的对应值为0int i,j,min,u; //初始化 将path dist s 数组的初值确定for(i=0 ; i<G.vexnum ; i++){dist[i]=G.edge[v][i]; //dist初值为源点到各个顶点的边的权值s[i]=0; //一开始没有一个顶点if(G.edge[v][i]<65535)path[i]=v; //与源点连通的顶点的path值存源点下标else path[i]=-1;//刚开始到源点没有路径的顶点path值为-1}s[v]=1; //源点加入集合spath[v]=-1; //源点不存在到自身的路径//下面的循环中包含两部分作用:①内层第一个for循环是找到 到剩余顶点中距离最小的 顶点u 并把它加入最短路径②内层第二个for循环是由新加入的顶点u来判断是否找到了新的更短路径,如果有就更新没有就不做任何操作for(i=0;i<G.vexnum;i++){min=65535;for(j=0;j<G.vexnum;j++){if(s[j]==0&&dist[j]<min){ //从剩余的顶点中找到距离最小的顶点u=j;//u用于保存当前找到的距离最小的顶点下标 当循环结束u保存的就是最小距离的顶点下标min=dist[j]; }}s[u]=1;//到u的距离是最小的,所以把顶点u加入最短路径for(j=0;j<G.vexnum;j++){if(s[j]==0 && dist[u]+G.Edges[u][j]<dist[j]){dist[j]=dist[u]+G.Edges[u][i];//如果由新加入最短路径的顶点u到其他剩余顶点的距离变短了则修改到剩余顶点的距离为较小值  path[j]=u;//这条较短的路径是由顶点u过来的  } }}
}

59.图的最短路径算法(Floyd算法)弗洛伊德

void Floyd(MGraph G,int Path[][]){int i, j, k ;int A[MaxSize][MaxSize];//对数组A[][]和Path[][]进行初始化for(i=0; i<G.vexnums; i++){for(j=0; j<G.vexnums; j++){A[i][j]=G.Edges[i][j];Path[i][j]=-1;}}for(k=0; k<G.vexnums; k++){for(i=0; i<G.vexnums; i++){for(j=0; j<G.vexnums; j++){if(A[i][j]>A[i][k]+A[k][j]){//如果顶点i到顶点j的距离比顶点i经过顶点k到顶点j的距离长,则更新从顶点i到顶点j的距离为较小值,并且存储k表示路径经过顶点kA[i][j]=A[i][k]+A[k][j];Path[i][j]=k;}}}}
}

查找

60.折半查找

int Binary_Search(SeqList L,ElemType key,int n){//L是一个顺序表,key是待查找的关键字,n是L的长度int low=0,high=n-1,mid;//low high mid 分别代表当前查找段的首位下标,末位下标和中间下标     while(low<=high){//只要low不和hig汇合,就表示查找表没有扫描完mid=(low+high)/2;//中间下标为low和high之和除2      if(L.elem[mid]==key)//查找成功return  mid;        else if(L.elem[mid]>key)//中间值比key大high=mid-1;   //由于有序,则key只可能在更小的地方出现   else//中间值比key小low=mid+1;  //key只可能在更小的地方出现}return  -1;
}

61.二叉排序树查找关键字(递归)

BiTNode *BST_Search(BiTNode *t,ElemType key){if(t==NULL)return NULL; //如果树为空则 返回空值else{if(t->key==key) return t;else if(key<t->key) return BST_Search(t->lchild,key);else return BST_Search(t->rchild,key);
}

62.二叉排序树查找关键字(非递归)

BiTNode * BST_Search(BiTNode *t,ElemType key){BiTNode *p=t;//工作指针 初值指向二叉排序树根结点while(p!=NULL && key!=p->data){//p不为空且没有找到keyif(key<p->data)  p=p->lchild;//如果key值比p指向结点值小,则查找左子树else  p=p->rchild;//如果key值比p指向结点值大,则查找右子树}return p;//查找成功返回指向值为key值的结点的指针 查找失败返回NULL
}

63.二叉排序树插入关键字

int BST_Insert(BiTNode* &t,ElemType k){ //插入操作是要对树进行修改,所以是引用类型的指针if(t==NULL){//原树为空,新插入的记录为根结点t=(BiTNode*)malloc(sizeof(BiTNode));//malloc库函数分配新结点的存储空间t->key=k;//该结点的关键字值赋值为kt->lchild=t->rhild=NULL;//根结点初始化左右孩子为空return  1;//返回1,表示成功}else if(k==t->key)//树中存在相同关键字的结点 插入失败return  0;else if(k<t->key)//插入到t的左子树中return  BST_Insert(t->lchild,k);else//插入到t的右子树中return  BST_Insert(t->rchild,k);
}

64.二叉排序树构造代码

void Creat_BST(BiTNode *&t,ElemType key[ ],int n){
//t是二叉排序树的根结点指针 key是关键字数组 n是关键字数量t=NULL;      //初始时t为空树int i=0;while(i<n){             BST_Insert(t,key[i]);i++;}
}

排序

65.直接插入排序

void InsertSort(ElemType A[],int n){int i,j;for(i=2;i<=n;i++){if(A[i].key<A[i-1].key){A[0]=A[i];//复制为哨兵,A[0]不存放元素for(j=i-1;A[0].key<A[j].key;--j)A[j+1]=A[j];//所有比待插入元素值大的都往后移一位,腾出空位A[j+1]=A[0];//复制到插入位置 }}
}

66.希尔排序

void ShellSort (ElemType A[],int n){int i,j;for(dk=n/2;dk>=1;dk=dk/2){//初始增量为总长度的一半,之后依次除2且向下取整,且最后一次要为1for(i=dk+1;i<=n;++i){if(A[i].key<A[i-dk].key){//A[i].key是待插入的关键字,i-dk之前的都是有序的,如果待插入的比有序序列最后一个小, 则需要进行排序(进入if语句块),如果大则不需要(跳出if语句块)A[0]=A[i]; //待插入关键字暂存在A[0]for(j=i-dk;j>0&&A[0].key<A[j].key; j-=dk)//待插入关键字之前以dk为增量的关键字只要比待插入关键字大的都往后移动dk位A[j+dk]=A[j];       A[j+dk]=A[0]; //找到了待插入的位置,就将待插入关键字插入这个位置           }}}
}

67.冒泡排序

void BubbleSort(ElemType A[],int n){for(i=0;i<n-1;i++){bool flag=false; //tips:当整个序列都有序的时候,标志位是不发生修改的,从而表示已经排好了 for(j=n-1;j>i;j--)          //一趟冒泡过程if(A[j-1].key>A[j].key){ //如果前面的元素比后面的大,则需要做交换ElemType temp=A[j-1].key;A[j-1].key=A[j].key;A[j].key=temp;  flag=true; //发生了数据交换修改标志位}if(flag==false)return ; //本趟遍历后没有发生交换,说明表已经有序}
}

68.快速排序

int Partition(ElemType A[],int low,int high){//low是当前待排序的序列起始下标,high是末尾下标ElemType pivot=A[low];//第一个元素作为枢轴while(low<high){while(low<high&&A[high]>=pivot) --high;//先从末尾往前找到第一个比枢轴小的元素A[low]=A[high];//用high的元素替换low的元素while(low<high&&A[low]<=pivot) ++low; //再从开头往后找到第一个比枢轴大的元素A[high]=A[low];//用low的元素替换high的元素}A[low]=pivot;//枢轴元素存放到最终位置return  low; //返回存放枢轴的最终位置
}
void QuickSort(ElemType A[],int low,int high){if(low<high){//low和high值要合法int pivotpos=Partition(A,low,high);QuickSort(A,low,pivotpos-1);//分治递归左半部分  QuickSort(A,pivotpos+1,high);//分治递归右半部分}
}

69.选择排序

void SelectSort(ElemType A[],int n){for(i=0;i<n-1;i++){//依次从后面序列中选择当前最小的元素作为第i个元素 最后一个元素不需要排序min=i;//min存的是当前最小元素所在下标,初值设为第i个for(j=i+1;j<n;j++)//从第i个元素往后找,一直要找到最后一个元素if(A[j]<A[min]) min=j;//如果这个值更小,则更新min值为这个更小的元素所在下标if(min!=i){//如果第i个元素不是剩下元素最小的,则和最小的进行交换ElemType temp=A[i];A[i]=A[min];A[min]=temp;}   }
}

70.堆排序

void BuildMaxHeap(ElemType A[],int len){for(int i=len/2;i>0;i--) AdjustDown(A,i,len);
}
void AdjustDown(ElemType A[],int k,int len){ A[0]=A[k];          for(i=2*k;i<=len;i*=2){                                             if(i<len&&A[i]<A[i+1])i++;if(A[0]>=A[i])  break;else{ A[k]=A[i];k=i;}}A[k]=A[0];
}
void HeapSort(ElemType A[],int len){BuildMaxHeap(A,len);//初始建堆for(i=len;i>1;i--){//n-1趟的交换和建堆过程//输出堆顶元素(和堆底元素交换)ElemType temp=A[i];A[i]=A[1];A[1]=temp;printf(A[i]);AdjustDown(A,1,i-1);//把剩余的i-1个元素整理成堆}
}

71.归并排序

ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType)); //辅助数组B(动态分配内存)void Merge(ElemType A[],int low,int mid,int high){
//表A的两段A[low…mid]和A[mid+1…high]各自有序,将它们合并成一个有序表for(int k=low;k<=high;k++) B[k]=A[k];//将A中所有元素复制到B中for(int i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){  //k是归并之后数组的下标计数器if(B[i]<=B[j])//比较B的左右两段中的元素A[k]=B[i++];//将较小值复制到A中elseA[k]=B[j++];}while(i<=mid)    A[k++]=B[i++];//若第一个表未检测完,直接将剩下的部分复制过来while(j<=high)    A[k++]=B[j++];//若第二个表未检测完,直接将剩下的部分复制过来
}
void MergeSort(ElemType A[],int low,int high){if(low<high){int mid=(low+high)/2;//从中间划分两个子序列MergeSort(A,low,mid);//对左侧子序列进行递归排序MergeSort(A,mid+1,high);//对右侧子序列进行递归排序Merge(A,low,mid,high);//归并}
}

73.拓扑排序

bool TopologicalSort(Graph G){InitStack(S);//初始化栈,存储入度为0的顶点for(int i=0;i<G.vexnum;i++)if(indegree[i]==0)Push(S,i);//将所有入度为0的顶点进栈int count=0;//计数,记录当前已经输出的顶点数while(!IsEmpty(S)){//栈不空,则存在入度为0的顶点Pop(S,i);//栈顶元素出栈pritnf(“%d”,G.adjlist[i]);for(ArcNode *p=G.vertices[i].firstarc; p; p=p->nextarc){v=p->adjvex; //取这条弧指向的顶点if(!(--indegree[v]))Push(S,v);//入度减1为0,则入栈}}if(count<G.vexnum)return  false;//排序失败,有向图中有回路else return  true;  //拓扑排序成功
}

数据结构考研(转载请标明出处,学习辛苦整理)相关推荐

  1. 大话“高可用”-Part1∶什么是高可用?(原创,转载请标明出处)

    很多人曾问过我,什么是高可用,你对高可用的理解是什么样子的,往往我会反问三个问题∶ 1.高可用 = 100%可用 ? 2.高可用= 真可用? 3.高可用的"可用"受众体是谁?你是否 ...

  2. 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jinjazz/archive/2009/04/29/4138000.aspx...

    using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Micr ...

  3. 片上总线Wishbone 学习—— 转载请注明出处:http://blog.csdn.net/ce123

    片上总线Wishbone 学习(零)前言 声明:版权所有,欢迎转载! 转载请注明出处:http://blog.csdn.net/ce123 为了更加升入的理解片上系统,比如S3C2440等,今天开始学 ...

  4. 引用请注明出处和转载请注明出处?我的看法

    很多文章和网站 都有这么一条: 引用请注明出处和转载请注明出处,有的无非多了个什么 保留法律权力 之类的 其实想想看,国外XX 小站 "拿去用了" 怎么办,起诉? BT下载&quo ...

  5. 手写多位数字识别器实现 (转载请注明出处!)

    1.主要功能 ①界面化的输入方式,进行实时数字识别 ②可以识别多位的数字,例如23,234 ③CNN进行数字识别 2.运行环境 Windows10.python3.7+.tensorflow2.x 3 ...

  6. uniapp:插件Luch_request 修改全局默认配置(转载请标明原创)

    目的是为了方便前端以后修改接口,以下是修改方法. 一.插件市场 导入 luch-request ,导入成功后,根目录有一个文件夹叫 js_sdk ,打开会发现有一个 luch-request 文件夹. ...

  7. 淘宝网的实习生笔试题以及经历--2011 4 1(转载请注明出处,即原创网址)

      昨天晚上7:00在西北工业大学,参加了淘宝网的实习生笔试(技术类),我应聘的是软件研发类.这一方面的人很多. 愚人节这一天,而且又下起了雨,路上车慢的很,感觉挺不顺利的,心情有点糟.到达笔试现场后 ...

  8. 面试常问的算法题,吐血总结,转载请注明出处,然后不要忘记点赞!

    面试常问的算法题,吐血总结,转载请注明出处,然后不要忘记点赞! 本人是硕士,西北地区一个末流211,投了四十家公司,面试了二十五次左右,公司大概有百度.阿里.腾讯.字节.华为.海康.美团(给我一天打了 ...

  9. 前端面试总结(转载请标明)

    最近在准备找工作,心理压力过大,把准备的面试题都整理出来了..刚刚把前端的整理好,后端的还在整理中..有哪里不对的还请大家指出 web前端优化 JS/CSS: JS会阻塞页面渲染,放在页面最下方: C ...

最新文章

  1. oracle io profile,ORACLE 中 PROFILE的管理
  2. 华为交换机ACL配置
  3. js导入导出总结与实践
  4. 一台服务器最多能创建多少个 TCP 连接?
  5. 【.NET Core项目实战-统一认证平台】第十一章 授权篇-密码授权模式
  6. KMP字符串比对算法理解
  7. html如何运用循环添加表格,萌新提问!!!如何用for循环循环表单?
  8. 追求代码质量: 不要被覆盖报告所迷惑
  9. php反向解析域名,域名系统 – Cloudflare,反向DNS和php邮件,最终在垃圾邮件文件夹中...
  10. PaddlePaddle(1)——让人拍案叫绝的创意都是如何诞生的
  11. 【UML】——为什么要使用UML
  12. Pytorch——对应点相乘+矩阵相乘
  13. 头条号小程序制作分享
  14. mysql查询最高分学生年龄_MySQL练习题student_score
  15. 完美生成年度节假日表,Kettle还能这么玩!
  16. 微信iOS WKWebview 网页开发适配指南
  17. Mac下文本编辑器无法生成html文件
  18. linux显卡可以sli吗,驱动设置 开启SLI功能_显卡_显卡技术应用-中关村在线
  19. PHP开发B2C商城 微信小程序商城系统源码+数据库,轻量级前后端分离的电商系统,支持微信小程序 + H5+ 公众号 + APP
  20. appollo消息服务器,Springboot 集成 MQTT —— web 服务端实现(apollo 客户端)-Go语言中文社区...

热门文章

  1. 360全景拼接 opencv_opencv实现的全景图种类与步骤
  2. 使用CAXA建立螺纹
  3. MySQL学习笔记(1)——高可用组复制
  4. 15 个优秀开源的 Spring Boot 学习项目,一网打尽!
  5. python嗅探工具详解附源码(使用socket,带tkinter界面)
  6. 51单片机LED模拟交通灯
  7. 【ubuntu】使用ubuntu杀死指定端口
  8. 如何用行式 Excel 数据制作不定行列的分组交叉统计表
  9. 为什么有的已备案域名的备案会被注销?
  10. 南昌大学计算机高级应用,南昌大学计算机应用技术调剂生复试经验