• 实现算法2.15、2.16的程序(一个数组只生成一个静态链表)


    // func2-2.cpp 实现算法2.15、2.16的程序,main2-31.cpp和main2-32.cpp调用
    int Malloc(SLinkList space) // 算法2.15(见图2.24)
    { // 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点);否则返回0
    	int i=space[0].cur;
    	if(i) // 备用链表非空
    		space[0].cur=space[i].cur; // 备用链表的头结点指向原备用链表的第二个结点
    	return i; // 返回新开辟结点的坐标
    }
    void Free(SLinkList space,int k) // 算法2.16(见图2.25)
    { // 将下标为k的空闲结点回收到备用链表(成为备用链表的第一个结点)
    	space[k].cur=space[0].cur; // 回收结点的"游标"指向备用链表的第一个结点
    	space[0].cur=k; // 备用链表的头结点指向新回收的结点
    }
    


    生成静态链表的方法可有两种:一种是在一个数组中只生成一个静态链表,这种情况
    可以固定静态链表的头指针位置,如最后一个单元([MAX_SIZE-1]);另一种是在一个数
    组中可根据需要生成若干个独立的链表,每个链表的头指针在生成链表时才指定。第一种
    方法指定数组名就指定了链表,函数的形参简单。但若在一个程序中用到多个链表,就需
    要定义多个数组,每个数组的备用链表不能互相调剂,空间浪费较大。第二种方法指定一
    个链表必须在指定数组名的同时指定链表的头指针位置,函数要多一个形参。bo2-31.cpp
    是第一种情况的基本操作,main2-31.cpp 是验证bo2-31.cpp 的主函数。

    // bo2-31.cpp 一个数组只生成一个静态链表(数据结构由c2-3.h定义)的基本操作(11个)包括算法2.13
    #define DestroyList ClearList // DestroyList()和ClearList()的操作是一样的
    void InitList(SLinkList L)
    { // 构造一个空的链表L,表头为L的最后一个单元L[MAX_SIZE-1],其余单元链成
    	// 一个备用链表,表头为L的第一个单元L[0],“0”表示空指针(见图2.26)
    	int i;
    	L[MAX_SIZE-1].cur=0; // L的最后一个单元为空链表的表头
    	for(i=0;i<MAX_SIZE-2;i++) // 将其余单元链接成以L[0]为表头的备用链表
    		L[i].cur=i+1;
    	L[MAX_SIZE-2].cur=0;
    }
    void ClearList(SLinkList L)
    { // 初始条件:线性表L已存在。操作结果:将L重置为空表
    	int i,j,k;
    	i=L[MAX_SIZE-1].cur; // 链表第一个结点的位置
    	L[MAX_SIZE-1].cur=0; // 链表空
    	k=L[0].cur; // 备用链表第一个结点的位置
    	L[0].cur=i; // 把链表的结点连到备用链表的表头
    	while(i) // 没到链表尾
    	{
    		j=i;
    		i=L[i].cur; // 指向下一个元素
    	}
    	L[j].cur=k; // 备用链表的第一个结点接到链表的尾部
    }
    Status ListEmpty(SLinkList L)
    { // 若L是空表,返回TRUE;否则返回FALSE
    	if(L[MAX_SIZE-1].cur==0) // 空表
    		return TRUE;
    	else
    		return FALSE;
    }
    int ListLength(SLinkList L)
    { // 返回L中数据元素个数
    	int j=0,i=L[MAX_SIZE-1].cur; // i指向第一个元素
    	while(i) // 没到静态链表尾
    	{
    		i=L[i].cur; // 指向下一个元素
    		j++;
    	}
    	return j;
    }
    Status GetElem(SLinkList L,int i,ElemType &e)
    { // 用e返回L中第i个元素的值
    	int l,k=MAX_SIZE-1; // k指向表头序号
    	if(i<1||i>ListLength(L))
    		return ERROR;
    	for(l=1;l<=i;l++) // 移动到第i个元素处
    		k=L[k].cur;
    	e=L[k].data;
    	return OK;
    }
    int LocateElem(SLinkList L,ElemType e) // 算法2.13(有改动)
    { // 在静态单链线性表L中查找第1个值为e的元素。若找到,则返回它在L中的
    	// 位序;否则返回0。(与其它LocateElem()的定义不同)
    	int i=L[MAX_SIZE-1].cur; // i指示表中第一个结点
    	while(i&&L[i].data!=e) // 在表中顺链查找(e不能是字符串)
    		i=L[i].cur;
    	return i;
    }
    Status PriorElem(SLinkList L,ElemType cur_e,ElemType &pre_e)
    { // 初始条件:线性表L已存在
    	// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱;
    	// 否则操作失败,pre_e无定义
    	int j,i=L[MAX_SIZE-1].cur; // i指示链表第一个结点的位置
    	do
    	{ // 向后移动结点
    		j=i;
    		i=L[i].cur;
    	}while(i&&cur_e!=L[i].data);
    	if(i) // 找到该元素
    	{
    		pre_e=L[j].data;
    		return OK;
    	}
    	return ERROR;
    }
    Status NextElem(SLinkList L,ElemType cur_e,ElemType &next_e)
    { // 初始条件:线性表L已存在
    	// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继;
    	// 否则操作失败,next_e无定义
    	int j,i=LocateElem(L,cur_e); // 在L中查找第一个值为cur_e的元素的位置
    	if(i) // L中存在元素cur_e
    	{
    		j=L[i].cur; // cur_e的后继的位置
    		if(j) // cur_e有后继
    		{
    			next_e=L[j].data;
    			return OK; // cur_e元素有后继
    		}
    	}
    	return ERROR; // L不存在cur_e元素,cur_e元素无后继
    }
    Status ListInsert(SLinkList L,int i,ElemType e)
    { // 在L中第i个元素之前插入新的数据元素e(见图2.27)
    	int l,j,k=MAX_SIZE-1; // k指向表头
    	if(i<1||i>ListLength(L)+1)
    		return ERROR;
    	j=Malloc(L); // 申请新单元
    	if(j) // 申请成功
    	{
    		L[j].data=e; // 赋值给新单元
    		for(l=1;l<i;l++) // 移动i-1个元素
    			k=L[k].cur;
    		L[j].cur=L[k].cur;
    		L[k].cur=j;
    		return OK;
    	}
    	return ERROR;
    }
    Status ListDelete(SLinkList L,int i,ElemType &e)
    { // 删除在L中第i个数据元素e,并返回其值(见图2.28)
    	int j,k=MAX_SIZE-1; // k指向表头
    	if(i<1||i>ListLength(L))
    		return ERROR;
    	for(j=1;j<i;j++) // 移动i-1个元素
    		k=L[k].cur;
    	j=L[k].cur;
    	L[k].cur=L[j].cur;
    	e=L[j].data;
    	Free(L,j);
    	return OK;
    }
    void ListTraverse(SLinkList L,void(*vi)(ElemType))
    { // 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi()
    	int i=L[MAX_SIZE-1].cur; // 指向第一个元素
    	while(i) // 没到静态链表尾
    	{
    		vi(L[i].data); // 调用vi()
    		i=L[i].cur; // 指向下一个元素
    	}
    	printf("
    ");
    }
    



    // main2-31.cpp 检验func2-2.cpp和bo2-31.cpp的主程序
    #include"c1.h"
    typedef int ElemType;
    #include"c2-3.h"
    #include"func2-2.cpp" // 两种方法都适用的函数在此文件中
    #include"bo2-31.cpp"
    #include"func2-3.cpp" // 包括equal()、comp()、print()、print2()和print1()函数
    void main()
    {
    	int j,k;
    	Status i;
    	ElemType e,e0;
    	SLinkList L;
    	InitList(L);
    	for(j=1;j<=5;j++)
    		i=ListInsert(L,1,j);
    	printf("在L的表头依次插入1~5后:L=");
    	ListTraverse(L,print);
    	i=ListEmpty(L);
    	printf("L是否空:i=%d(1:是0:否)表L的长度=%d
    ",i,ListLength(L));
    	ClearList(L);
    	printf("清空L后:L=");
    	ListTraverse(L,print);
    	i=ListEmpty(L);
    	printf("L是否空:i=%d(1:是0:否)表L的长度=%d
    ",i,ListLength(L));
    	for(j=1;j<=10;j++)
    		ListInsert(L,j,j);
    	printf("在L的表尾依次插入1~10后:L=");
    	ListTraverse(L,print);
    	GetElem(L,5,e);
    	printf("第5个元素的值为%d
    ",e);
    	for(j=0;j<=1;j++)
    	{
    		k=LocateElem(L,j);
    		if(k)
    			printf("值为%d的元素在静态链表中的位序为%d
    ",j,k);
    		else
    			printf("没有值为%d的元素
    ",j);
    	}
    	for(j=1;j<=2;j++) // 测试头两个数据
    	{
    		GetElem(L,j,e0); // 把第j个数据赋给e0
    		i=PriorElem(L,e0,e); // 求e0的前驱
    		if(!i)
    			printf("元素%d无前驱
    ",e0);
    		else
    			printf("元素%d的前驱为%d
    ",e0,e);
    	}
    	for(j=ListLength(L)-1;j<=ListLength(L);j++) // 最后两个数据
    	{
    		GetElem(L,j,e0); // 把第j个数据赋给e0
    		i=NextElem(L,e0,e); // 求e0的后继
    		if(!i)
    			printf("元素%d无后继
    ",e0);
    		else
    			printf("元素%d的后继为%d
    ",e0,e);
    	}
    	k=ListLength(L); // k为表长
    	for(j=k+1;j>=k;j--)
    	{
    		i=ListDelete(L,j,e); // 删除第j个数据
    		if(i)
    			printf("第%d个元素为%d,已删除。
    ",j,e);
    		else
    			printf("删除第%d个元素失败(不存在此元素)。
    ",j);
    	}
    	printf("依次输出L的元素:");
    	ListTraverse(L,print); // 依次对元素调用print(),输出元素的值
    }

    运行结果如下:

    /*
    在L的表头依次插入1~5后:L=5 4 3 2 1
    L是否空:i=0(1:是0:否)表L的长度=5
    清空L后:L=
    L是否空:i=1(1:是0:否)表L的长度=0
    在L的表尾依次插入1~10后:L=1 2 3 4 5 6 7 8 9 10
    第5个元素的值为5
    没有值为0的元素
    值为1的元素在静态链表中的位序为5
    元素1无前驱
    元素2的前驱为1
    元素9的后继为10
    元素10无后继
    删除第11个元素失败(不存在此元素)。
    第10个元素为10,已删除。
    依次输出L的元素:1 2 3 4 5 6 7 8 9
    Press any key to continue
    */


  • 相关阅读:
    创建线程的方式三:实现Callable接口 --- JDK 5.0新增
    线程的通信
    多线程的实例练习:银行账户双储户问题
    解决线程安全问题的方式三:Lock锁 --- JDK5.0新增
    演示线程的死锁问题
    Synchronized的各场景使用方法(多窗口售票例子接上篇)
    线程的【生命周期】和【线程的同步】(下面有多窗口售票例子)
    多线程:继承方式和实现方式的联系与区别
    创建多线程的方式二:实现Runnable接口
    Java项目生成可执行jar包、exe文件以及在Windows下的安装文件
  • 原文地址:https://www.cnblogs.com/KongkOngL/p/4074480.html
Copyright © 2020-2023  润新知