C语言实现链表数据结构

/*
ADT 线性表list
Data
	满足特征的数据,每个元素类型为DataType
Opration
	InitList(L):    初始化操作,建立一个空的线性表
	ListEmpty(L):   若线性表为空,返回ture,否则false
	ClearList(L):   清空线性表
	GetElem(L,i,*e):将L中第i个元素返回给e
	LoacateElem(L,e):在L中查找与e相等元素,返回位置,没有返回0
	ListInsert(*L,i,e):在L的第i个元素位置插入e
	ListDelete(*L,i,*e):在L的第i个元素位置删除,并用e返回
	ListLength(L)   :返回线性表L的元素个数
endADT
*/
1.线性表的顺序储存结构实现
顺序结构需要三个条件;指定一个存储空间Maxsize;其次要知道存储的位置data[];最后要知道长度length
//顺序存储的结构实现
#include <stdio.h>
#include <Windows.h>
#define MAXSISZ 20
typedef int ElemType;
typedef struct
{
	ElemType data[MAXSISZ];
	int length;
}SqList;
2.线性表顺序存储的操作
查找、插入、删除、取值、修改
2.1 线性表顺序存储取值操作
两步即可完成:
1.判断位置是否合法
2.见数组值赋值返回
//顺序存储元素获取,从1开始
#define ERROR 0
#define OK 1
#define True	1
#define False	0
typedef int Status; //定义返回位置
Status GetElem(SqList L,int i,ElemType* e)
{
	if (i>L.length ||i<1 ||L.length==0)
	{
		return ERROR;
	}
	*e =L.data[i-1];
	return OK;
}
2.2线性表顺序存储插入值操作
完成步骤:
1.判断插入条件
2.从后往前移动一个位置
3.在i的位置停止,赋值
Status ListInsert(SqList *L,int i,ElemType e)
{
	if (L->length==MAXSISZ)
		return ERROR;
	if (i>L->length+1 || i<0)  //i超出范围
		return ERROR;
	if (i<=L->length)
	{
		for (int j=L->length;j>=i-1;j--)
			L->data[j+1]=L->data[j];
		L->length = L->length+1;
		L->data[i-1]=e;
		return OK;
	}
}
2.3线性表顺序存储删除元素操作
步骤:
1.检查合法性,非法抛出异常(i>length;i<0;)
2.从i开始前移一个位置
3.表长减1
Status ListDelete(SqList *L,int i, ElemType *e)
{
	if (i<0)
		return ERROR;
	if (i>L->length)
		return ERROR;
	if (i>0 && i<=L->length)
	{
		*e=L->data[i-1];
		for (int j=i-1;j<=L->length;j++)
		{
			L->data[j]=L->data[j+1];
		}
		return OK;
	}
}
3.线性表的链式存储结构
3.1 链表的定义与结构
定义:像铁链一样的结构的线性表,铁链的每个环称为结点
结点(node):铁链的一环,可以分为两部分:一部分用来扩张长度;一部分用来连接下一环;因此:结点是由数据域和指针域构成;铁链的头可能系的绳子:头指针
3.2 链表的分类
结点的定义:数据元素由数据域和指针域构成
typedef struct Node
{
	ElemType data;  //数据域
	struct Node *next; //指针域
}Node;
typedef struct Node *LinkList;  //定义了一个头指针,指向node

3.2.1.单链表
a. 单链表的读取:
步骤:
1.从头开始,不断读取下一个,直至返回
2.未读取到时返回空
Status GetElemLinkList(LinkList L,int i,ElemType *e)
{
	LinkList p; //声明一个指针
	p=L->next;  //p指向l的首个指针
	int j = 1;  //计数
	while (p && j<i)
	{
		p->next;
		j++;
	}
	if(!p || j>i)
		return ERROR;
	*e =p->data;
	return OK;
}
b. 单链表的插入:
步骤:
1.循环读取定位到位置i
2.生成一个空结点,存放e
3.指针指向e地址,e的指针指向下一结点
Status LinkListInsert(LinkList l,int i, ElemType e)
{
	LinkList p,s;    //声明一个指针
	p=l->next;     //p指向l的首结点
	int j = 1;    //计数器
	while (p && j<i)
	{
		p->next;
		j++;
	}
	if (!p ||j>i)
	{
		return ERROR;
	}
	s = (LinkList)malloc(sizeof	(Node));  //生成一个新结点
	s->data = e;   //结点赋值
	s->next=p->next;  //新结点指向下一结点
	p->next=s;        //指向新结点
	return OK;
}
c. 单链表的删除:
步骤:
1.循环读取定位到位置i
2.指针指向下下个
3.释放结点,返回e
Status LinkListDelete(LinkList l,int i ,ElemType *e)
{
	LinkList p,q;
	p =l->next;
	int j =1;
	while(p->next && j<i-1)
	{
		p=p->next;
		j++;
	}
	if (!(p->next)||j>i)
		return ERROR;
	q=p->next;  //用q指向i
	p->next=q->next;//将i指向换为i-1指向
	*e=q->data;
	free(q);
	return OK;
}
d. 单链表的创建(头插法)
定义:所谓头插法,就是指每个新结点都放在第一位
步骤:
1.产生一个空链表L
2.声明指针p和计数器l
3.l的头结点指向null
4.循环插入新结点
void CreateListHead(LinkList* l,int n)
{
	LinkList p;
	int i;
	srand(time(0));   //随机数种子
	*l = (LinkList)malloc(sizeof(Node)); //产生一个头结点为空的链表l,为变量分配内存
	(*l)->next=NULL;      //初始化指向空
	for (i=0;i<n;i++)    //新结点插入l
	{
		p=(LinkList)malloc(sizeof(Node));
		p->data=rand()%100+1;
		p->next = (*l)->next;    //单链表的标准插入方法,p的next指向下一个结点
		(*l)->next = p;          //l指向p
	}
}

e.单链表的创建(尾插法)
void CreateListTail(LinkList* l,int n)
{
	LinkList p,r;
	int i;
	srand(time(0));
	*l = (LinkList)malloc(sizeof(Node));
	r = *l;   //r为指向尾部的结点,尾插法,最重要的是知道尾结点的地址
	for (i=0;i<n;i++)
	{
		p = (LinkList)malloc(sizeof(Node));
		p->data = rand()%100+1;
		r->next=p;   //尾结点的指针指向p
		r=p;
	}
	r->next = NULL;   //尾结点指向空
}
f.单链表的清空
Status ClearSList(LinkList *l)
{
	LinkList p,q;
	p = (*l)->next;
	while (p)
	{
		q=p->next;
		free(p);
		p=q;
	}
	(*l)->next=NULL;  //头结点指向空
	return OK;
}
双链表
循环链表
静态链表

f:测试入口
void main()
{
	/*
	//线性表顺序存储的测试用例
	SqList  l;
	l.length = 10;
	ElemType e;
	for (int i=0;i<l.length;i++)
	{
		l.data[i]=i;
	}
	GetElem(l,3,&e);
	ListInsert(&l,3,5);      //在第三个位置插入5
	ListDelete(&l,3,&e);
	printf("%d\n",l.data[2]);   //&e表示引用e的地址,e为一个变量;*e表示e指向的内容,e为一个指针变量
	system("pause");
	*/
	/*
	单链表的单元测试
	*/
	ElemType e;
	LinkList  m;   //声明一个结点
	m = NULL;       //结点初始化为空
	CreateListHead(&m,10);   //头插法创建单链表
	//printList(&m);
	CreateListTail(&m,10);    //尾插法创建链表
	printList(&m);
	LinkListDelete(m,2,&e);   //单链表删除第i个元素,返回给e
	printList(&m);
	LinkListInsert(m,2,99);   //单链表的插入,第2个位置插入99
	printList(&m);
	GetElemLinkList(m,2,&e);   //单链表的查询,获取第2个元素的值,返回给e
	printf("%d\n",e);
	ClearSList(&m);           //清空单链表
	printList(&m);
	system("pause");	
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值