数据结构课程设计(部分选题)

数据结构课设(部分选题)


一、必做题:双向循环链表操作的实现

  1. 建立一个空表。
  2. 在第i个位置插入新的元素x。
  3. 删除第i个位置上的元素。
  4. 取第i个位置上的元素。
  5. 返回元素x第一次出现在双向循环链表中的位置号。
  6. 求双向循环链表的长度,即元素个数。
  7. 输出双向循环链表中所有的元素值。
  8. 实现双向循环链表的就地逆置。

代码如下:

DuLinkList类:

import java.util.Scanner;

public class DuLinkList
{
    public DuLNode head;       //头结点
    public DuLinkList()
    {
        //初始化:1)头结点,2)前驱,3)后继;
        head=new DuLNode();
        head.prior=head;
        head.next=head;
    }
    //逆向创建循环链表,n为节点个数
    public DuLinkList(int n) throws Exception
    {
        this();
        Scanner sc = new Scanner(System.in);
        for(int j=0;j<n;j++)
        {
            insert(0,sc.next());    //生成新节点插入到表头
        }
    }
    //获取长度
    public int length()
    {
        DuLNode p = head.next;
        int length = 0;
        while(!p.equals(head))
        {
            p = p.next;
            ++length;
        }
        return length;
    }

    //头插法创建链表P46算法2.9
    public void creatList(int n) throws Exception
    {
        Scanner sc=new Scanner(System.in);
        for(int j=0;j<n;j++)
        {
            insert(0, sc.next());
        }
    }
    //获取数据元素与P41算法2.4相同,只不过在双向列表中从首节点向后查找是直到p与head相等(即回到了原先的结点)是就认为到达了尾结点
    public Object get(int i)throws Exception
    {
        DuLNode p=head.next;
        int j=0;
        while (!p.equals(head)&&j<i)
        {
            p=p.next;
            ++j;
        }
        if(j>i)
        {
            throw new Exception("第"+i+"个元素不存在!");
        }
        return p.data;
    }
    //插入数据元素P54
    public void insert(int i, Object x)throws Exception
    {
        DuLNode p=head.next;
        int j=0;
        while (!p.equals(head)&&j<i)
        {
            p=p.next;
            ++j;
        }
        if(i>=j+1)

            throw new Exception("插入位置不合法!");
        DuLNode s=new DuLNode(x);
        p.prior.next=s;
        s.prior=p.prior;
        s.next=p;
        p.prior=s;
        System.out.println("插入成功!");
    }
    //删除数据元素
    public void remove(int i)throws Exception
    {
        DuLNode p=head.next;
        int j = 0;
        //指针没走完双向链表的前提下,从第0个元素开始寻找删除的位
        while (!p.equals(head)&&j<i)
        {
            p=p.next;
            ++j;
        }
        if(j!=i)
        {
            throw new Exception("删除节点不合法");
        }
        //断开两条链,建立两条新的链
        p.prior.next=p.next;    //p结点的上一个结点的后继next指向下一个结点的前驱prior
        p.next.prior=p.prior;   //p结点的下一个结点的前驱prior指向上一个结点的后继next
        System.out.println("删除成功!");
    }
    //获得元素下标
    public int indexOf(Object x) {
        DuLNode p = head.next;
        int j = 0;
        //双向链表不为空并且数据元素与所输入的元素比较以后不相等
        while (!p.equals(head) && !p.data.equals(x))
        {
            p = p.next;      //指针后移
            ++j;           //计数器加1
        }
        //在双向链表没有走完一次的情况下,就找到了位置j,走完了就说明,没有找到返回-1
        if (!p.data.equals(x))
        {
            return -1;
        }
        else
            {
            return j;
            }
    }
    //输出双向列表数据
    public void display()
    {
        DuLNode node=head.next;
        while(!node.equals(head))
        {
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println();
    }
    //就地逆置
    public void exList()
    {
        DuLNode p=head.next;
        DuLNode q=p.next;
        int n=length();
        for(int i=0;i<=n;i++)
        {
            q = p.next;			//交换p的前驱、后继中的地址信息
            p.next = p.prior;
            p.prior = q;
            p=q;				//p后移
        }
        display();
    }
}

DuLNode类:

public class DuLNode
{
    public Object data;
    public DuLNode prior;
    public DuLNode next;
    public DuLNode()
    {
        this(null);
    }
    public DuLNode(Object data)
    {
        this.data=data;
        this.prior=null;
        this.next=null;
    }
}

Test类:

import java.util.Scanner;

public class Test
{
    public static void main(String[] args)throws Exception
    {
        Scanner sc=new Scanner(System.in);
        DuLinkList list = new DuLinkList();
        System.out.println("新建空链表成功");
        for(int i=0;;i++)
        {
            System.out.println("1:插入结点及其信息\t2:删除结点\t3:查找数据元素\t4查找元素下标\t5:链表长度\t6:链表所有结点\t7:就地逆置\t8:初始化链表\t9:退出程序");
            System.out.println("请输入要执行的操作编号!");
            int choose=sc.nextInt();
            switch(choose)
            {
                case 1:
                    System.out.println("请输入所插入的位置及节点信息:");
                    list.insert(sc.nextInt(), sc.next());
                    break;
                case 2:
                    System.out.println("请输入所删除的结点的位置:");
                    list.remove(sc.nextInt());
                    break;
                case 3:
                    System.out.println("请输入所查找的结点的位置:");
                    System.out.println("所查找的数据元素为:"+list.get(sc.nextInt()));
                    break;
                case 4:
                    System.out.println("请输入所查找的数据元素:");
                    System.out.println("您所查找的元素第一次出现的位置为: "+list.indexOf(sc.next()));
                    break;
                case 5:
                    System.out.println("该链表的长度为"+list.length());
                    break;
                case 6:
                    System.out.println("链表的所有数据元素为:");
                    list.display();
                    break;
                case 7:
                    System.out.println("链表的逆置结果为:");
                    list.exList();
                    break;
                case 8:
                    System.out.println("请输入要创建链表的的结点个数:");
                    int n=sc.nextInt ();
                    System.out.println("请逆序输入链表的数据元素:");
                    list.creatList(n);
                    break;
                case 9:
                    System.out.println("程序已终止");
                    System.exit(9);
                    break;
                default :
                    System.out.println("输入有误");
                    break;
            }

        }

    }

}

二、题目6:树的孩子兄弟表示法及相关操作:
使用孩子-兄弟表示法作为树的存储结构,求树中结点的个数、求树的深度、求结点的孩子个数、实现树的先根、后根和层次遍历。
代码如下:
CSTree类:


import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class CSTree
{
	public CSTreeNode root;	
	public CSTree()
	{
		this.root=null;
	}	
	public CSTree(CSTreeNode root)
	{
		this.root=root;
	}	
	//由先根遍历序列建立一颗孩子兄弟树
	private static int index=0;                    //记录T的索引值		
	public CSTree(String T)
	{
		char c=T.charAt(index++);                  //取出字符串索引为index的字符,且index加1即index ++;
		if(c!='#')
		{           
			//字符#表示无后继结点			
			root=new CSTreeNode(c);              	  	 //建立树的根结点
			root.firstchild=new CSTree(T).root;   	 //建立树的左子树
			root.nextsibling=new CSTree(T).root;   //建立树的右子树
		}
		else
		{
			root=null;
		}
	}
	private int i=0;
	//树中结点个数
	public int countNode(CSTreeNode T)
	{
		int count=0;
		if(T!=null)
		{
			++count;
			count+=countNode(T.firstchild);	//左孩子的节点数加1
			count+=countNode(T.nextsibling);
		}
		return count;
	}
	//树的深度
	public int getDepth(CSTreeNode T)
	{
		if(T!=null)
		{
		int LDepth = getDepth(T.firstchild);
		int rDepth = getDepth(T.nextsibling); 
		return 1+ (LDepth > rDepth ? LDepth : rDepth);
		}
		else
			return 0;
	}
	//求结点的孩子个数
	int a ;
	public void countChildNode(String X,CSTreeNode T){
		if(T!=null){
			if(X.equals(T.data.toString())) 
			{
				if(T.firstchild!=null) 
				{
					T = T.firstchild;
					for(a=1;a<countNode(T)&&T.nextsibling!=null;a++) 
					{
						T = T.nextsibling;
					}
				}
				System.out.println("孩子结点为"+a);
			}
			else
			{
				countChildNode(X,T.firstchild);
				countChildNode(X,T.nextsibling);
			}	
		}
	}
	//树的先根遍历
	public void preRootTraverse(CSTreeNode T)
	{
		if(T!=null)
		{
			System.out.println(T.data);
			preRootTraverse(T.firstchild);
			preRootTraverse(T.nextsibling); 	
		}
	}
	//树的后根遍历
	public void postRootTraverse(CSTreeNode T)
	{
		if(T!=null)
		{
			postRootTraverse(T.firstchild);
			System.out.println(T.data);
			postRootTraverse(T.nextsibling);
		}
	}
	//层次遍历
	public void level(CSTreeNode T)
	{
		Queue L = new LinkedList();		
		L.offer(T);                      //入队
		while(L.isEmpty()!=true)
		{
			CSTreeNode s = (CSTreeNode) L.poll();
			System.out.println(s.data + " ");
			if(s.firstchild!=null)
			{
				L.offer(s.firstchild);
			}
			if(s.nextsibling!=null)
			{
				L.offer(s.nextsibling);
			}
		}		
	}	
	public static void main(String[] args)
	{
		Scanner sc=new Scanner(System.in);
        System.out.println("请输入结点:");
        String T1 = sc.next();
//		输入样例:ABC##DE##F###
		CSTree T=new CSTree(T1);	
		System.out.println("输出的节点数为"+T.countNode(T.root));	
		System.out.println("树的深度为:"+T.getDepth(T.root));	
		System.out.println("先根遍历结果是:");
		T.preRootTraverse(T.root);
		System.out.println("后根遍历结果是:");
		T.postRootTraverse(T.root);
		System.out.println("层次遍历结果是:");
		T.level(T.root);	
		System.out.println("请输入要计算的孩子的结点:");
		String t=sc.next();
		T.countChildNode(t,T.root);
		sc.close();
	}
}

CSTreeNode类:


public class CSTreeNode 
{
	public Object data;
	public CSTreeNode firstchild,nextsibling;
	public CSTreeNode(){
		this(null);
	}
	public CSTreeNode(Object data){
		this(data,null,null);
	}
	public CSTreeNode(Object data,CSTreeNode firstchild,CSTreeNode nextsibling){
		this.data=data;
		this.firstchild=firstchild;
		this.nextsibling=nextsibling;
	}			
}

三、题目九、已知港沟卫生职业技术学院校园各楼之间的距离,如何用最小的代价布置网线使各楼互连并通信?要求使用两种算法实现。
代码如下:
arcNode:

public class arcNode
{
    int value;//权值
    int adjVex;//该弧指向的前一顶点的位置
    int nextVex;//该弧指向的后一顶点的位置
    arcNode nextArc;//指向下一条弧
    public int getValue()
    {
        return value;
    }
    public void setValue(int value)
    {
        this.value = value;
    }
    public int getAdjVex()
    {
        return adjVex;
    }
    public void setAdjVex(int adjVex)
    {
        this.adjVex = adjVex;
    }
    public int getNextVex()
    {
        return nextVex;
    }
    public void setNextVex(int nextVex)
    {
        this.nextVex = nextVex;
    }


    public arcNode()
    {
        this.adjVex = -1;
        this.nextVex = -1;
        this.value = -1;
        this.nextArc = null;
    }
    public arcNode(int value)
    {
        this.adjVex = -1;
        this.nextVex = -1;
        this.value = value;
        this.nextArc = null;
    }
    public arcNode(int u,int v,int value)
    {
        this.adjVex = u;
        this.nextVex = v;
        this.value = value;
        this.nextArc = null;
    }

}

Graph:


import java.util.Scanner;

public class Graph
{
    int arcNum,vexNum;      //边的数量、顶点的数量
    VNode [] vexs;          //顶点数组的定义(存储顶点)
    arcNode [] arcs;        //边数组的定义(存储边)
    public int getArcNum()
    {
        return arcNum;
    }
    public int getVexNum()
    {
        return vexNum;
    }


    //创建带权值的图,无向图;
    Graph()
    {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入教学楼的数量:");
        vexNum = sc.nextInt();
        System.out.println("请输入连接各教学楼的道路的数量:");
        arcNum = sc.nextInt();
        vexs = new VNode[vexNum];//创建有n个值顶点数组
        arcs=new arcNode[arcNum*2];//创建有n个值边数组
        System.out.println("请输入各教学楼的名称:");
        for(int i=0;i<vexNum;i++)
        {
            vexs[i] = new VNode(sc.next());
        }

        System.out.println("请输入各条路连接的教学楼名称及每条路的长度:");

        //依次给顶点数组赋值(教学楼名称、路的长度)

        for(int j=0;j<arcNum;j++)
        {
            int v=locateVex(sc.next());
            int u=locateVex(sc.next());
            int value = sc.nextInt();
            addArc(u,v,value);
            addArc(v,u,value);
            arcs[j]=new arcNode(u,v,value);
            arcs[j+arcNum]=new arcNode(v,u,value);
        }
        //对边数组按权值进行排序,由小到大
        for(int i=0;i<arcs.length;i++)
        {
            for(int j=0;j<arcs.length-1;j++)
            {
                if(arcs[j].value>arcs[j+1].value)
                {
                    arcNode temp=arcs[j];
                    arcs[j]=arcs[j+1];
                    arcs[j+1]=temp;
                }
            }
        }
        sc.close();
    }
    Graph(int vex,int arc,VNode[] vexs)
    {
        this.arcNum=arc;
        this.vexNum=vex;
        this.vexs=vexs;
    }
    //添加边结点
    void addArc(int v,int u,int value)
    {
        arcNode arc = new arcNode(value);
        arc.adjVex=v;
        arc.nextVex=u;
        arc.nextArc = vexs[v].firstArc;
        vexs[v].firstArc = arc;
    }
    //根据输入的顶点名称查找顶点在邻接表中的位置,并返回位置号
    int locateVex(Object vex)
    {
        for(int i=0;i<vexNum;i++)
        {
            if(vexs[i].data.equals(vex))
            {
                return i;
            }
        }
        return -1;
    }
    public VNode[] getVex()
    {
        return vexs;
    }
    //查找第一个邻接点
    int firstAdjVex(int v)
    {
        if(v<0&&v>=vexNum)
        {
            System.out.println("第"+v+"个结点不存在!");
        }
        VNode vex = vexs[v];
        if(vex.firstArc!=null)
        {
            return vex.firstArc.adjVex;
        }
        else
            return -1;
    }
    //查找下一个邻接点
    int nextAdjVex(int v,int w)
    {
        if(v<0&&v>=vexNum)
        {
            System.out.println("第"+v+"个结点不存在!");
        }
        VNode vex = vexs[v];
        arcNode arcvw = null;
        for(arcNode arc=vex.firstArc;arc!=null;arc=arc.nextArc)
        {
            if(arc.adjVex==w)
            {
                arcvw = arc;
                break;
            }
        }
        if(arcvw!=null&&arcvw.nextArc!=null)
            return arcvw.nextArc.adjVex;
        else
            return -1;
    }
    //获取第v个结点
    public Object getVex(int v) throws Exception
    {
        if (v < 0 && v >= vexNum)
            throw new Exception("第" + v + "个顶点不存在!");

        return vexs[v].data;
    }


    //克鲁斯卡尔算法求最小生成树
    void kruskal()
    {
        int k=0;
        int sn1,sn2;
        int[] vset = new int[vexNum];//定义一个辅助数组用来记录两个顶点间是否连通
        for(int i=0;i<vexNum;i++)
        {
            vset[i] = i;
        }
        k = 1;
        int j = 0;
        while(k<vexNum)
        {
            //最小生成树边数为:vexNum-1'边的数减去1
            sn1 = vset[arcs[j].adjVex];//用vest数组标记arcNode的前驱节点
            sn2 = vset[arcs[j].nextVex];//用vest数组标记arcNode的后继节点
            if(sn1!=sn2)
            {
                //如果sn1和sn2不相等 则不形成环,打印出这条边
                System.out.println(vexs[arcs[j].adjVex].data+"<---->"+vexs[arcs[j].nextVex].data);
                k++;
            }
            for(int i=0;i<vexNum;i++)
            {
                if(vset[i]==sn2)
                {//判断是否能够形成环
                    vset[i]=sn1;//形成了就再找新的顶点
                }
            }
            j++;
        }
    }
    //获取以i,j为顶点的边
    int getArcs(int i,int j)
    {
        for(int k=0;k<arcs.length;k++)
        {
            if(arcs[k].adjVex==i&&arcs[k].nextVex==j)
            {
                return arcs[k].value;
            }
        }
        return Integer.MAX_VALUE;
    }
    // 内部类辅助记录从顶点U到V-U的代价最小的边
    private class CloseEdge
    {
        Object adjVex;
        int lowCost;

        public CloseEdge(Object adjVex, int lowCost)
        {
            this.adjVex = adjVex;
            this.lowCost = lowCost;
        }
    }

    // 用Prime算法从第u个顶点出发构造网G的最小生成树T,返回由生成树边组成的二维数组
    public Object[][] PRIM(Graph G, Object u) throws Exception
    {
        Object[][] tree = new Object[getVexNum() - 1][2];
        int count = 0;
        CloseEdge[] closeEdge = new CloseEdge[getVexNum()];//记录U-U-v的边的集合
        int k = locateVex(u);
        for (int j = 0; j < getVexNum(); j++)
        {
            // 辅助数组初始化
            if (j != k)
            {
                closeEdge[j] = new CloseEdge(u, getArcs(k, j));

                closeEdge[k] = new CloseEdge(u, 0);// 初始,U={u}
            }
        }
        for (int i = 1; i < getVexNum(); i++)
        {
            // 选择其余G.vexnum - 1个顶点
            k = getMinMum(closeEdge);// 求出T的下一个结点:第k个顶点
            tree[count][0] = closeEdge[k].adjVex;// 生成树的边放入数组
            tree[count][1] = vexs[k].data;
            count++;
            closeEdge[k].lowCost = 0;// 第k个顶点并入U集
            for (int j = 0; j < getVexNum(); j++)
            {
                //新顶点并入U后重新选择最小边
                if (getArcs(k, j) < closeEdge[j].lowCost)
                {
                    closeEdge[j] = new CloseEdge(getVex(k), getArcs(k, j));
                }
            }
        }
        return tree;
    }

    //在closeEdge中选出lowCost最小且不为0的顶点
    private int getMinMum(CloseEdge[] closeEdge)
    {
        int min = Integer.MAX_VALUE;
        int v = -1;
        for (int i = 0; i < closeEdge.length; i++)
        {
            if (closeEdge[i].lowCost != 0 && closeEdge[i].lowCost < min)
            {
                min = closeEdge[i].lowCost;
                v = i;
            }
            return v;
        }
        return min;
    }

}

TestGraph:

public class TestGraph
{
    public static void main(String args[]) throws Exception
    {

        Graph a = new Graph();
        System.out.println("kruskal算法求出的最小代价方案为:");
        a.kruskal();

        System.out.println("Prim算法求出的最小代价方案为:");
        Object[][] tree = a.PRIM(a,a.getVex(0));
        for(int i=0;i<tree.length;i++)
        {
            System.out.println(tree[i][1]+"<--->"+tree[i][0]);
        }

    }

}

VNode:

public class VNode
{
    Object data;

    arcNode firstArc;//指向第一条依附于该节点的弧

    VNode()
    {
        this.data = null;
        this.firstArc = null;
    }
    VNode(Object data)
    {
        this.data = data;
        this.firstArc = null;
    }

}

以上代码为初步未修改版本,仅供参考,欢迎各位批评指正。

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Walker_CodeGou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值