zoukankan      html  css  js  c++  java
  • 关于单链表,二叉树,图,查找和排序的软件编程

    课程名称:计算机软件

    使用软件:devcpp

    注意:这里列出了关于单链表,二叉树,图,查找和排序的编程,全部程序由博主一人编写,会有瑕疵,谨慎使用。

    1.单链表

    要求:(1)建立单向链表,表长任意;

               (2)可交互输出单链表中的内容;

               (3)编写算法计算出自己所建单链表的长度并输出;

               (4)删除自己所建单链表中的第K个结点,并将剩余结点输出;

               (5)将单链表倒排,输出结果。

    程序:

    #include <stdio.h> 
    #include <stdlib.h>

    //定义链表中的节点 
    struct node
    {  unsigned char data;//链表中的数据 
       struct node * next;//指向下一节点的指针 
    };

    //变量定义
    struct node  *p,*p1,*p2,*head;

    //函数声明
    void ListCreate();
    void ListTraverse();
    void ListLength();
    int ListDelete();
    int ListReverse();

    //主函数 
    int main()
    {
     ListCreate();        //单向链表的建立
     ListTraverse();      //单向链表的输出
     ListLength();        //单向链表长度计算
     ListDelete();        //单向链表结点的删除
     ListReverse();      //单链表的倒排 
    }

    //单向链表的建立
    void ListCreate()
    {   
        head=p=(struct node * )malloc(sizeof(struct node));
     printf("请输入链表数据元素值(0为结束标志,中间不能用任何符号): "); 
        scanf("%c",&p->data);//头结点的数据成员 
        while(p->data!='0')//给出0结束条件,退出循环
        {   
       p1=p; 
          p=(struct node * )malloc(sizeof(struct node)); 
          scanf("%c",&p->data);//中间结点数据成员
          p1->next=p;//中间结点的指针成员值
        } 
        p->next=NULL;//尾结点的指针成员值 
    }

    //单向链表的输出
    void ListTraverse()

        p=head;
        printf(" 链表数据成员是:"); 
        while(p->next!=NULL) 
        { 
          printf("%c  ",p->data);  //输出成员数据
          p=p->next; 
        }   
    }

    //单向链表长度计算
    void ListLength()
    {
        p2=head->next;
        int  j=1;            //j用来存放链表的长度
        while((p2->data)-48)
        {
          p2=p2->next;
          j++;
        }
        printf(" 链表长度是:  %d",j);
    }

    //单向链表结点的删除
    int ListDelete()
    {
        p2 = head;

        int j = 1,M,K;
       
        printf(" 要删除第几个节点: ");
     scanf("%d",&K);

        if ( j > (K-1)) //删除头节点
       {
          struct node  *p3;
          p3=p2;
          p2=p3->next;
        }
        else   //删除其它节点
        {
        while ((p2->next)-48 && j < (K-1))
     {
            p2 = p2->next;
            ++j;
        }
         if (p2->next == NULL )
     {
            printf("Position Error ");
            return 0;
        }
        struct node *temp = p2->next;  //执行删除操作
        p2->next = temp->next;
        }   
        p=head;
        printf("删除后的链表数据成员是:"); 
        while(p->next!=NULL) 
        { 
          printf("%c  ",p->data);  //输出成员数据
          p=p->next; 
        } 
    }

    //单链表的倒排
    int ListReverse()
    {
        struct node *h,*h1,*h2;
        h=head;
        h1=h;                    
        h=NULL;
        while(h1->next!=NULL)      //通过循环使h从最后一个元素依次向前
        { 
            h2 = h1->next; 
            h1->next = h; 
            h = h1; 
            h1 = h2;
        }  
        printf(" 倒排后的链表数据成员是:"); 
        while(h!=NULL)  //输出数据元素
        { 
          printf("%c  ",h->data); 
          h=h->next; 
        }  
    }

    难点:单链表的倒排,这里有两种方法实现

    1)逆序单链表的循环算法:

     1 LINK_NODE *ReverseLink(LINK_NODE *head)
     2     {
     3         LINK_NODE *next;
     4         LINK_NODE *prev = NULL;
     5     
     6         while(head != NULL)
     7         {
     8             next = head->next;
     9             head->next = prev;
    10             prev = head;
    11             head = next;
    12         }
    13     
    14         return prev;
    15     }

    2)逆序单链表的递归算法:

     1 LINK_NODE *ReverseLink2(LINK_NODE *head)
     2    {
     3         LINK_NODE *newHead;
     4     
     5         if((head == NULL) || (head->next == NULL))
     6             return head;
     7     
     8         newHead = ReverseLink2(head->next); /*递归部分*/
     9         head->next->next = head; /*回朔部分*/
    10         head->next = NULL;
    11     
    12         return newHead;
    13    }

    循环还是递归?这是个问题。当面对一个问题的时候,不能一概认为哪种算法好,哪种不好,而是要根据问题的类型和规模作出选择。对于线性数据结构,比较适合用迭代循环方法,而对于树状数据结构,比如二叉树,递归方法则非常简洁优雅。原文链接:https://blog.csdn.net/lycnjupt/article/details/47103433

    如果想了解关于逆序单链表的其它实现方法,可以查看链接:

    http://blog.sina.com.cn/s/blog_68e4d2910100tc0i.html

    2.二叉树

    要求:(1)动态交互建立二叉树,结点个数任意;

               (2)分别用DLR,LDR,LRD三种方式对二叉树进行遍历,并输出结果;

               (3)计算二叉树中的结点个数并输出;

               (4)计算二叉树的深度并输出。

    我自己的程序:

    #include <stdio.h>
    #include <stdlib.h>

    //节点声明,数据域、左指针、右指针
    typedef struct BiTNode
    {
       int data;//二叉树数据元素
       struct BiTNode *Left,*Right;//二叉树左右指针
    }BiTNode,*BiTree;

    //函数声明
    int CreateBiTree(BiTNode **T);
    void DLR_BiTree(BiTNode *T);
    void LDR_BiTree(BiTNode *T);
    void LRD_BiTree(BiTNode *T);
    int BiTreeCount(BiTNode *T);
    int BiTreeDeep(BiTNode *T);

    //主函数
    int main()
    {
       BiTree T;
       int depth,Count = 0;
      
       printf("请输入第一个节点的值(0表示没有该节点): ");
       CreateBiTree(&T);//二叉树建立
       printf(" ");
      
       printf("先序遍历二叉树:");
       DLR_BiTree(T);//二叉树先序遍历
       printf(" ");
      
       printf("中序遍历二叉树:");
       LDR_BiTree(T);//二叉树中序遍历
       printf(" ");
      
       printf("后序遍历二叉树:");
       LRD_BiTree(T);//二叉树后序遍历
       printf(" ");
      
       Count = BiTreeCount(T);//求二叉树结点个数  
       printf("二叉树结点个数:%d ",Count); 
      
       depth = BiTreeDeep(T);//求二叉树深度 
       printf("二叉树的深度为:%d ",depth);
    }

    //先序创建二叉树 
    int CreateBiTree(BiTNode **T) 

        int ch; 
        scanf("%d",&ch);//给二叉树第一个节点赋值 
        if (ch == 0) 
        { 
            *T = NULL;  //输入为0表示没有该节点
            return 0; 
        } 
        else 
        { 
            *T = (BiTNode *)malloc(sizeof(BiTNode));  //给二叉树节点分配内存
            if (T == NULL) 
            { 
                printf("failed "); 
                return 0; 
            } 
            else 
            { 
                (*T)->data = ch; 
                printf("输入%d的左子节点:",ch); 
                CreateBiTree(&((*T)->Left));  //递归给二叉树左节点赋值
                printf("输入%d的右子节点:",ch); 
                CreateBiTree((&(*T)->Right)); //递归给二叉树右节点赋值
            } 
        } 
     
        return 1; 
    }

    //二叉树先序遍历
    void DLR_BiTree(BiTNode *T)
    {
     if( T == NULL) return;//递归调用的结束条件
     printf("%d",T->data);//访问节点的数据域
     DLR_BiTree(T->Left);//先序递归遍历左子树
     DLR_BiTree(T->Right);//先序递归遍历右子树
    }

    //二叉树中序遍历
    void LDR_BiTree(BiTNode *T)
    {
     if(T==NULL) return;//递归调用的结束条件
     LDR_BiTree(T->Left);//中序递归遍历左子树
     printf("%d",T->data);//访问节点的数据域
     LDR_BiTree(T->Right);//中序递归遍历右子树
    }

    //二叉树后序遍历
    void LRD_BiTree(BiTNode *T)
    {
     if(T==NULL) return;//递归调用的结束条件
     LRD_BiTree(T->Left);//后序递归遍历左子树
     LRD_BiTree(T->Right);//后序递归遍历右子树
     printf("%d",T->data);//访问节点的数据域
    }

    //求二叉树结点个数
    int BiTreeCount(BiTNode *T)
    {
        if(T==NULL)
            return 0;//空二叉树结点数为0
        else                           
            return BiTreeCount(T->Left)+BiTreeCount(T->Right)+1;//左右子树结点总数加1
    }
     
    //求二叉树深度
    int BiTreeDeep(BiTNode *T) 

        int deep = 0; 
        if (T != NULL) 
        { 
            int leftdeep = BiTreeDeep(T->Left);//递归得到左子树深度 
            int rightdeep = BiTreeDeep(T->Right);//递归得到右子树深度
            deep = leftdeep >= rightdeep?leftdeep+1:rightdeep+1;//比较得到二叉树深度 
        } 
     
        return deep; 

    3.图

    要求:(1)根据教材上算法,完成图的深度和广度优先遍历,要求任意给定起始点,输出结果。

              (2)根据教材上算法,完成图的单元最短路径的算法,要求任意给定源点,输出结果。

    程序:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXVEX  100                      //最大顶点数  
    #define INFINITY 65535                //用65535来代表无穷大  
    
    //定义访问标记 
    int visited[MAXVEX]={0};  
      
    //定义图结构体  
    typedef struct  
    {  
        char vexs[MAXVEX];                //顶点表  
        int  arc[MAXVEX][MAXVEX];         //邻接矩阵,可看作边  
        int  numVertexes, numEdges;       //图中当前的顶点数和边数  
    }Graph;   
    
    //辅助数组中的元素定义  
    typedef struct 
    {  
        int distance;  
        int path[MAXVEX];  
    }ArrayNode;
    
    //函数声明
    void CreateGraph(Graph *g);
    void DFS(Graph g,int v);
    void BFS(Graph g,int v);
    void SHORT(Graph *g,int from,int to);
    void SHORT(Graph *g,int from,int to);
    
    //主函数 
    int main()
    {
    	Graph g;
    	int i,from,to;
    	printf("t为1-4,分别表示无向图、有向图、带权无向图、带权有向图
    ");
        CreateGraph(&g);//创建图 
        
        printf("
    输入遍历起点: ");  
        scanf("%d",&i);  
        printf("
    深度优先搜索遍历:");
        DFS(g,i);//深度优先遍历函数 
        printf("NULL
    ");
        
        printf("广度优先搜索遍历:"); 
        BFS(g,i);//广度优先遍历函数 
        printf("NULL
    ");
        
        printf("
    Dijkstra算法单元最短路径:");
        printf("
    请输入起点和终点(中间用空格):");
        scanf("%d %d",&from,&to);
        SHORT(&g,from,to);//Dijkstra算法单元最短路径函数	
    }
      
    //创建图  
    void CreateGraph(Graph *g)  
    {    
         int i,j,k,w,t;  
         printf("输入顶点数,边数和t(中间用空格):");  
         scanf("%d %d %d", &(g->numVertexes), &(g->numEdges),&t);  
         printf("
    ");  
         for(i=1;i<=g->numVertexes;i++)//通过循环输入顶点信息  
         {  
         getchar();  
         printf("输入第%d顶点信息vexs[%d]=",i,i);  
         scanf("%c",&(g->vexs[i]));  
         }  
         printf("
    ");  
         for(i=1;i<=g->numVertexes;i++)  
            for(j=1;j<=g->numVertexes;j++)  
                    if (t>2)    g->arc[i][j] = INFINITY;//区别是否带权值  
                    else        g->arc[i][j]=0;   
         for(k=1;k<=g->numEdges;k++)//通过循环输入边的信息  
               {  
                printf("输入有联系的两个顶点(中间用空格):");  
                scanf("%d %d",&i,&j);  
                if(i>g->numVertexes ||j>g->numVertexes)  exit(0);  
                if(t>2)  
                {  
                      printf("输入权值:");  
                      scanf("%d",&w);  
                      g->arc[i][j]=w;  
                      if(t==3)  g->arc[j][i]=w;  
                }  
                else  
                {     g->arc[i][j]=1;  
                      if (t==1)    g->arc[j][i]=1;  
                }  
         }  
         printf("
    ");  
         printf("输出邻接矩阵:
    ");  
         for(i=1;i<=g->numVertexes ;i++)  
         {  
         for(j=1;j<=g->numVertexes ;j++)  
         {  
         printf("%8d",g->arc[i][j]);  //输出邻接矩阵 
           
         /*if(t>2&&g->arc[i][j]==65535)  
           g->arc[i][j]=0;  
         else if(t>2&&g->arc[i][j]!=65535)  
                  g->arc[i][j]=1; */ 
         }  
          printf("
    ");  
         }  
    }  
    
    //深度优先遍历
    void DFS(Graph g,int v)
    {
        int j;  
        printf("%d->",v);         //输出访问顶点  
        visited[v]=1;            //全局数组访问标记置1表示已经访问  
        for(j=1; j<=g.numVertexes; j++)  
           if ((g.arc[v][j]!=0)&&(g.arc[v][j]!=65535)&&(!visited[j]))  
                DFS (g,j);//递归访问非0非无穷顶点 
    } 
    
    //广度优先遍历
    void BFS(Graph g,int v)
    {
    	int  q[g.numVertexes+1] ;  
        int  i,f,r,j ;
    	for(i=0;i<g.numVertexes;i++)
    	visited[i]=0;  //重置访问标记 
        f=r=0 ;  
        printf("%d->",v);//输出第一个顶点  
        visited[v]=1 ;//标记已访问  
        r++;  
        q[r]=v;  
        while (f<r)  
        {    
    	  f++; 
    	  v=q[f];  
          for (j=1; j<=g.numVertexes; j++) //广度优先遍历依次访问与上一顶点有联系的点 
            {
    		if ((g.arc[v][j]!=0)&&(g.arc[v][j]!=65535)&&(!visited[j]))  
            {       
    		    printf("%d->",j);//输出访问顶点 
    		    visited[j]=1 ;     
    		    r++; 
    	    	q[r]=j ;  
    		}
    		}  
        }  
    } 
    
    //单元最短路径算法
    void SHORT(Graph *g,int from,int to)
    {
    	int i,j,index=-1;  
        int n=1;//记录已经求出的两个点之间的最短距离的个数  
        ArrayNode shortestPath[MAXVEX];  
        int flag[MAXVEX]={0};//标记,为1表示到这个顶点的最短距离已求出  
       
        //1.求from到各个顶点的直接距离,即初始化shortestPath数组  
        for(i=1;i<=g->numVertexes;i++)
    	{  
            if(from==i)
    		{  
                shortestPath[i].distance=0;  
                shortestPath[i].path[0]=i;  
                flag[from]=1;  
            }  
            else if(g->arc[from][i]>0)
    		{  
                shortestPath[i].path[0]=from;  
                shortestPath[i].path[1]=i;  
                shortestPath[i].distance=g->arc[from][i];  
            }
    		else 
                shortestPath[i].distance=INFINITY;  
        }  
        //2.每次求一个最短路径  
        while(n<=g->numVertexes)
    	{  
            //选择shortestPath中距离最小的,求出from到这个顶点的最短路径  
            index=-1;  
            for(i=1;i<=g->numVertexes;i++)
    		{  
                if(i==from)  
                    continue;  
                if(flag[i]==0 && index==-1 && shortestPath[i].distance!=INFINITY)  
                    index=i;  
                if(flag[i]==0 && index!=-1 && shortestPath[i].distance<shortestPath[index].distance)  
                    index=i;  
            }  
            flag[index]=1;  
            //修改到各个顶点的最短路径  
            for(i=1;i<=g->numVertexes;i++)
    		{  
                if(i==from)  
                    continue;  
                if(g->arc[index][i]>0 && g->arc[index][i]+shortestPath[index].distance<shortestPath[i].distance)
    			{  
                    shortestPath[i].distance=g->arc[index][i]+shortestPath[index].distance;  
                    //修改路径  
                    j=0;  
                    while(1)
    				{  
                        shortestPath[i].path[j]=shortestPath[index].path[j];  
                        if(shortestPath[index].path[j]==index)  
                            break;  
                        j++;  
                    }  
                    shortestPath[i].path[j+1]=i;  
                }  
            }  
            n++;  
        }  
        //输出from到to的最短路径及长度  
        if(shortestPath[to].distance==INFINITY){  
            printf("%d到%d没有路径
    ",from,to);  
            return;  
        }  
        printf("%d到%d的最短路径长度是:%d
    ",from,to,shortestPath[to].distance);  
        printf("经过的顶点:  ");  
        i=0;  
        while(1){  
            printf("%-3d",shortestPath[to].path[i]);  
            if(shortestPath[to].path[i]==to)  
                break;  
            i++;  
        }  
        printf("
    ");
    } 
    

    4.查找和排序

    要求:(1)任意给定无序序列,用对半检索法,交互检索任意给定的关键字KEY;

               (2)任意给定无序序列,用快速排序法对序列进行排序,并统计交换次数;

               (3)任意给定无序序列,用冒泡排序法对序列进行排序,并统计交换次数和排序趟数。

    程序:

    #include "stdio.h"
    #define N 6//序列长度(可修改)
    
    //函数声明 
    int halfSort(int *b,int n); 
    void quickSort(int *b,int l,int r);
    void bubbleSort(int *bb,int r);
    
    //全局变量定义 
    int o,p,k;
    int KEY; //检索的关键字 
    
    //主函数 
    int main()
    {
    	int i,j,q;
    	int a[100],aa[100],aaa[100];//以数组方式定义序列 
    	printf("Hello World!
    ");
    	
    	printf("
    1.请输入任意序列(用回车隔开)
    ");
    	for(i=1;i<=N;i++)
    	scanf("%d",&a[i]);//输入无序序列 
    	quickSort(a,1,N);//先排序再进行对半检索
    	printf("排序后序列为:");
    	for(j=1;j<=N;j++)
    	printf("%d ",a[j]);//输出有序序列 
    	printf("
    请输入需要检索的关键字KEY:"); 
    	scanf("%d ",&KEY);
        q=halfSort(a,N);//对半检索函数调用 
        printf("对半检索-关键字位置为:%d
    ",q);
        
        printf("
    2.请输入任意序列(用回车隔开)
    ");
    	for(i=0;i<N;i++)
    	scanf("%d",&aa[i]);//输入无序序列 
        quickSort(aa,0,N-1);//快速排序函数调用 
        printf("快速排序后序列为:");
    	for(j=0;j<N;j++)
    	printf("%d ",aa[j]);//输出有序序列 
    	printf("
    交换次数为:%d
    ",k);
    	
    	printf("
    3.请输入任意序列(用回车隔开)
    ");
    	for(i=0;i<N;i++)
    	scanf("%d",&aaa[i]);//输入无序序列 
    	bubbleSort(aaa,N);
    	printf("冒泡排序后序列为:");//冒泡排序函数调用 
    	for(j=0;j<N;j++)
    	printf("%d ",aaa[j]);//输出有序序列 
    	printf("
    交换次数为:%d
    ",o);
    	printf("排序趟数为:%d
    ",p);
    	
    	return 0; 
    }
    
    //对半检索函数 
    int halfSort(int *b,int n)
    {
    	int high,mid,low;
    	int rs=0;
    	low=1;high=n;//初始状态 
    	while(low<=high)//判断查找是否结束 
    	{
    		mid=(low+high)/2;
    		if(KEY<b[mid]) high=mid-1;//关键字在前半区 
    		else
    		if(KEY>b[mid]) low=mid+1;//关键字在后半区 
    		else {rs=mid;break;}
    	}
    	return rs;
    }
    
    //快速排序函数 
    void quickSort(int *bb,int l,int r)
    {
       int m,n;
       int temp;
       if(l>=r) return;//只有一个记录或无记录,无须排序 
       m=l;
       n=r;
       temp=bb[m];
       while(m!=n)//寻找temp的最终位置 
       {
       while((bb[n]>=temp)&&(n>m))
       n--;//从右向左扫描,查找第一个小于temp的记录 
       if(m<n)
       {bb[m++]=bb[n];k++;}
       while((bb[m]<=temp)&&(n>m))
       m++;//从左向右扫描,查找第一个大于temp的记录 
       if(m<n)
       {bb[n--]=bb[m];k++;}
       }
       bb[m]=temp;//找到temp的最终位置 
       quickSort(bb,l,m-1);//递归处理左区间 
       quickSort(bb,m+1,r);//递归处理右区间 
    }
    
    //冒泡排序函数 
    void bubbleSort(int *bbb,int r)
    {
    	int m,n,noswap;
    	int temp;
    	for(m=0;m<(r-1);m++)//外循环,做N-1次起泡 
    	{
    		noswap=1;
    		for(n=0;n<(r-m-1);n++)//内循环,置交换标志 
    		if(bbb[n+1]<bbb[n])//比较 
    		{
    			temp=bbb[n];
    			bbb[n]=bbb[n+1];
    			bbb[n+1]=temp;//交换 
    			o++;
    			noswap=0;
    		}
    		if(noswap) break;//本趟起泡未发生记录交换,算法结束 
    		p++;
    	}
    }
    

      

  • 相关阅读:
    国内大学毕业论文LaTeX模板集合
    LATEX论文排版学习资源汇总
    论文神器Latex30分钟快速入门教程-只需9步向学神看齐
    smartdraw2013破解方法
    科研常用的软件
    推荐科研软件
    斯坦福大学科研软件
    【LaTeX】E喵的LaTeX新手入门教程(6)中文
    【LaTeX】E喵的LaTeX新手入门教程(5)参考文献、文档组织
    【LaTeX】E喵的LaTeX新手入门教程(4)图表
  • 原文地址:https://www.cnblogs.com/BoBoRing/p/8886094.html
Copyright © 2011-2022 走看看