线性表的链式表示和实现

上传源码,学习交流,有什么需要改进的地方还希望各位给予指点。

参考书目:《数据结构(C语言版)》,严蔚敏

common.h

#ifndef	_COMMON_H_
#define	_COMMON_H_


#define TRUE	    1
#define FALSE		0
#define OK			1
#define ERROR		0
#define INFEASIBLE  -1
#define OVERFLOW	-2

typedef int Status;


int	   Equal(int x,int y);	//判断两个数据是否相等

#endif


common.c

/*
输入参数:x、y		待标胶的两个数
返回参数:若x与y相等,则返回0,否则返回1
函数功能:判断两个整型数是否相等
*/
int Equal(int x,int y)
{
	if(x==y)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}


list.h

#ifndef _LIST_H_
#define _LIST_H_

#define ElemType int


/*链表结构*/
typedef struct List_
{
	ElemType      data;
	struct List_   *next;
}List;

void   InitList(List *L);
int    ListAdd(List *L,unsigned int index, ElemType data);
int    ListDelete(List *L, unsigned int index, ElemType *data);
int    ListDisp(List *L);
int    ListScanf(List *L);
unsigned int  ListLength(List *L);
int	   GetElem(List *L,unsigned int i,int *e);
int    LocateElem(List *L,int e,int (*f)());
int    ListInsert(List *L,unsigned int n,int e);	//该函数与ListAdd()类似,但建议用这个函数。

#endif


list.c

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
//#include "common.h"


/*
输入参数:*L     待初始化的链表头结点
返回参数:无
函数功能:对链表头结点进行初始化
*/
void InitList(List *L)
{
	L->data = 0;
	L->next = NULL;
}


/*
输入参数:*L      待插入链表头结点
           index   加入位置(从1开始)(例如:原链表是x(0)=10、x(1)=11、x(2)=12、x(3)=13、x(4)=14、……,现在想在第2个结点插入数字100,则得到的新链表是x(0)=10、x(1)=11、x(2)=100、x(3)=12、x(4)=13、x(5)=14、……)
							(暂时不能在第0点插入,即不能插入新的链表头)
           data    加入的数据
返回参数:0       成功
		   非0     失败(可以细分具体的参数分别代表什么意思)
函数功能:在链表的指定位置插入数据,
 */
int ListAdd(List *L,unsigned int index, ElemType data)
{
	List *p = NULL;
	List *newNode = NULL;

	if(L == NULL || index == 0) return -1;  //输入参数错误

	p = L;
	while(p != NULL && (--index > 0))
	{
		p = p->next;
	}

	if(p == NULL)   return -2;     //插入位置错误

	newNode = (List *)malloc(sizeof(List));
	if(newNode == NULL)
	{
		return -3;     //内存错误
	}

	newNode->data = data;
	newNode->next = p->next;
	p->next = newNode;

	return 0;   //成功
}

/*
输入参数:*L  待插入链表的头结点
返回参数:-1  该链表不存在
			0  成功完成向链表输入数据
函数功能:向指定的链表输入数据,每输完一个数据按下回车,约定当输入0时自动终止输入,且不将0存入链表。
*/
int ListScanf(List *L)
{
	int n;
	List	*p1,*p2;
	
	n=0;
	p1=L;
	p2=L;

	if(L == NULL)	
	{
		return -1;	//该链表不存在
	}
	//p1=(List *)malloc(sizeof(List));
	scanf("%d",&p1->data);	//在向*p1指向的内存赋值时,一定要先使p1指向一个确定的存储空间。(L在别处已经定义过,是有存储空间的,所以将L赋给p也是可以的。)
	//p1->next = NULL;	//这条语句也可以不要,因为L的next已经在函数ListInit(List *L)中定义过了。
	while(p1->data!=0)
	{
		p2->next=p1;	//当第一次进入该循环时,p2实际上是指向自己的。
		p2=p1;
		p1=(List *)malloc(sizeof(List));
		if(p1 == NULL) return -3;	//内存不够用
		scanf("%d",&p1->data);
		p1->next=NULL;
	}
	p2->next = NULL;
	free(p1);
	return 0;	//完成向链表输入数据。
}


/*
输入参数:*L     待删除链表头结点
		   index  删除位置(从1开始)
		                   (暂时不能删除第0点的数据,即不能删除链表头)
           data   保存删除的数据
返回参数:0      成功
           非0    失败
函数功能:删除链表中的指定位置的数据
*/
int ListDelete(List *L, unsigned int index, ElemType *data)
{
	List *p = NULL;
	List *q = NULL;
	
	if(L == NULL || index == 0) return -1;   //头结点为空

	p = L;
	while(p->next != NULL && (--index > 0)) 
	{
		p = p->next;
	}
	if(p->next == NULL)
	{
		return -2;       //删除位置错误
	}

	q = p->next;
	p->next = q->next;
	if(data != NULL)   *data = q->data;
	free(q);

	return 0;    //成功

}

/*
输入参数:*L     待显示的链表头结点
返回参数:0      成功
           非0    失败
函数功能:显示链表中的所有数据(从第0位开始显示,即从头结点开始显示)
 */
int ListDisp(List *L)
{
	List *p = NULL;

	if(L == NULL)   return -1;   //链表不存在

	p = L;

	printf("\n**************** output start ****************\n");
	while(p != NULL)
	{
		printf("%d  ", p->data);
		p = p->next;
	}
	printf("\n**************** output end ****************\n\n\n\n");


	return 0;
}

/*
输入参数:*L	待测试链表的头结点
返回参数:链表长度
函数功能:测量链表中数据元素的个数(即链表长度),若返回0则表示该链表中没有数据,即该链表不存在。
*/
unsigned int ListLength(List *L)
{
	List *p = L;
	int n = 0;
	//if(p == NULL)	return -1;	//该链表不存在
	while(p != NULL)
	{
		n++;
		p = p->next;
	}
	return n;
}

/*
输入参数:L	待查找链表头
		   i	待提取元素的位置(从0开始,即从链表头开始),0 ≤ i ≤ ListLength(&L)
		   *e	将待提取元素赋给e所指变量
返回参数:-1	链表长度不够
			0	成功
			(也可以直接放回第i个元素的值)
函数功能:将链表L中的第i个元素的值赋给e所指变量
*/
int GetElem(List *L,unsigned int i,int *e)
{
	List *p=L;
	int n=0;
	if(i >= ListLength(L)) return -1;	//链表长度不够
	while(n!=i)
	{
		p = p->next;
		n++;
	}
	*e = p->data;
	return 0;	//成功
}

/*
输入参数:L		待操作链表的链表头
		   e		待比较元素
		   (*f)()	判定关系
返回参数:0~ListLength(&L)		返回L中第1个与e满足关系(*f)()的数据元素的为序
		   -1	链表L中不存在这样的数据元素
函数功能:返回L中第1个与e满足关系(*f)()的数据元素的为序,若这样的数据元素不存在,则返回-1
*/
int LocateElem(List *L,int e,int (*f)())
{
	int n=0;
	List *p=L;

	while(p != NULL)
	{
		if((*f)(p->data,e) == 0)
		{
			return n;
		}
		p = p->next;
		n++;
	}
	return -1;
}

/*
输入参数:*L	待插入的链表头
			n	待插入位置
			e	待插入数据
返回参数:-1	插入位置错误
			0	插入成功
函数功能:在指定位置插入数据
*/
int ListInsert(List *L,unsigned int n,int e)
{
	List *p = L,*newnode=NULL;
	int i = 1;
	if(p == NULL)	return -1;	//其实这一条在下面的语句也可以判断出来。
	if(n == 0 || n > ListLength(L))
		return -1;	//插入位置错误
	while(i != n)
	{
		p = p->next;
		i++;
	}
	newnode = (List *)malloc(sizeof(List));
	newnode->data = e;
	newnode->next = p->next;
	p->next = newnode;
	return 0;
}


example.h

#ifndef _EXAMPLE_H_
#define	_EXAMPLE_H_

void UnionList(List *La,List *Lb);
void MergeList(List *La,List *Lb,List *Lc);

#endif


example.c

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "common.h"

/*
例2-1
输入参数:*La	待合并线性表La
		   *Lb	待合并线性表Lb
返回参数:无
函数功能:扩大线性表La,将存在于Lb而不存在于La中的数据元素插入到La中去
*/
void UnionList(List *La,List *Lb)
{
	unsigned int i,La_len,Lb_len;
	int Li;
	La_len = ListLength(La);
	Lb_len = ListLength(Lb);
	for(i = 0; i < Lb_len; i++)
	{
		GetElem(Lb,i,&Li);
		//printf("%d",Li);
		if(LocateElem(La,Li,Equal) == -1)
		{
			ListInsert(La,La_len,Li);
			La_len++;
		}
	}
}

/*
例2-2
输入参数:*La/*Lb	待归并链表头结点
		   *Lc		归并后的链表
返回参数:无
函数功能:合并链表La和Lb于Lc
*/
void MergeList(List *La,List *Lb,List *Lc)
{
	unsigned int i=0,j=0,k=0,La_len,Lb_len;
	int ai=0,bj=0;
	La_len = ListLength(La);
	Lb_len = ListLength(Lb);
	while((i < La_len) && (j < Lb_len))
	{
		GetElem(La,i,&ai);
		GetElem(Lb,j,&bj);
		if(ai <= bj)
		{
			if(k==0)  Lc->data = ai;
			else  ListInsert(Lc,k,ai);
			k++;
			i++;
		}
		else
		{
			if(k==0)  Lc->data = bj;
			else  ListInsert(Lc,k,bj);
			k++;
			j++;
		}
	}
	while(i < La_len)
	{
		GetElem(La,i,&ai);
		i++;
		ListInsert(Lc,k,ai);
		k++;
	}
	while(j < Lb_len)
	{
		GetElem(Lb,j,&bj);
		j++;
		ListInsert(Lc,k,bj);
		k++;
	}
}	//end of MergeList


main.c

//参考书目:《数据结构(C语言版)》,严蔚敏
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "common.h"
#include "example.h"

int main(void)
{
	List La,Lb,Lc;
	int Li=0;

	InitList(&La);
	InitList(&Lb);

	printf("输入La\n");
	ListScanf(&La);		//约定当输入0时自动终止输入
	ListDisp(&La);
	
	printf("输入Lb\n");	
	ListScanf(&Lb);		//约定当输入0时自动终止输入
	ListDisp(&Lb);

	printf("合并La与Lb于Lc,并显示Lc\n");
	InitList(&Lc);
	MergeList(&La,&Lb,&Lc);
	ListDisp(&Lc);

	return 0;
}


运行输出结果如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线性表是一种常见的数据结构,它包含了一组有序的元素,元素之间具有前驱和后继关系。线性表链式表示是其中一种实现方式。 线性表链式表示通过使用节点和指针来表示表中元素之间的关系。具体来说,每个节点中都包含了一个元素和一个指向下一个节点的指针。通过不断地遍历指针,就可以顺着链表找到表中的所有元素。 链式表示的优点是可以动态地插入和删除元素,而不需要移动其他元素。这是因为链表中的节点通过指针相互连接,可以在任意位置插入和删除元素。同时,链式表示可以节省内存空间,因为节点不需要连续的存储空间,可以灵活地分配内存。 实现链式表示的方式是使用结构体来定义节点和指针。节点结构体中包含了一个元素和一个指向下一个节点的指针。使用指针的方式可以实现链表节点之间的相互连接。 在C语言中,可以通过定义一个节点结构体来表示链表的节点,然后使用指针指向链表的头节点。通过遍历指针,可以遍历整个链表,并对链表进行插入、删除等操作。 总之,线性表链式表示通过节点和指针的方式来实现表中元素之间的关系。链式表示可以动态地插入和删除元素,并且节省内存空间。在C语言中,可以通过定义节点结构体和指针来实现链式表示实现链表的各种操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值