【大话数据结构】线性表:顺序表和链表

线性表(List):零个或多个数据元素的有限序列。

一般复杂操作基本可以用基本操作组合而成,比如GetElem、LocateElem、ListInsert、ListDelete、ListLength等。


顺序存储结构—顺序表

用一段地址连续的存储单元依次存储线性表的数据元素。比如C语言的一维数据。结构图示:


顺序存储结构的缺点是插入和删除时需要移动大量元素。

一般操作示例:

#define MAXSIZE 20
typedef int ElemType;  /*元素类型假设为int*/
typedef struct
{
	ElemType data[MAXSIZE];    /*数组的长度,开辟存储空间长度,一般不变,初动态分配数组*/
	int length;                /*线性表当前长度,数据元素的个数,随着插入删除操作变化着*/
}SqList;

/*取数组L中第i个元素给e*/
void GetElem(SqList L, int i, ElemType *e)
{
	if (L.length == 0 || i<1 || i>L.length)
		return;
	*e = L.data[i - 1];
}

/*在第i个元素前插入新的元素e,L的长度增加1*/
void ListInsert(SqList *L, int i, ElemType e)
{
	int k;
	if (L->length == MAXSIZE || i<1 || i>L->length + 1)
		return;
	if (i <= L->length)        /*插入位置不在表尾时,把后面的元素均向后移动一位*/
	{
		for (k = L->length - 1; k >= i - 1; k--)
			L->data[k + 1] = L->data[k];
	}
	L->data[i - 1] = e;
	L->length++;
}

/*删除L的第i个元素,其值给e,长度减1*/
void ListDelete(SqList *L, int i, ElemType *e)
{
	int k;
	if (L->length == 0 || i<1 || i>L->length)
		return;
	*e = L->data[i - 1];
	if (i < L->length)         /*删除的不是最后元素,后面元素向前移*/
	{
		for (k = i; k < L->length; k++)
			L->data[k - 1] = L->data[k];
	}
	L->length--;
}


链式存储结构—链表

用一组任意的存储单元存储数据元素,这些存储单元可以是连续的,也可以是不连续的。

这就是链表。存储单元就是结点(Node)。结点 = 数据域 + 指针域(指示后继的存储位置),结构图示为:


以下是链表的几种:

单链表

单链表的结构(左)和 空链表的结构(右):

   

一般操作示例:

typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node;
typedef struct Node *LinkList;

/*取链表中第i个数据元素的值给e*/
void GetElem(LinkList L, int i, ElemType *e)
{
	LinkList p;         /*声明一结点p*/
	p = L->next;        /*让p指向链表L的第一个结点*/
	int j;
	j = 1;              /*计数器j*/
	while (p && j<i)    /*p不为空且j还没有到i*/
	{
		p = p->next;
		++j;
	}
	if (!p || j>i)
		return;     /*第i个元素不存在*/
	*e = p->data;
}

/*在链表L中第i个位置之前插入新的元素e,L长度加1*/
void ListInsert(LinkList *L, int i, ElemType e)
{
	LinkList p, s;
	p = *L;
	int j;
	j = 1;
	while (p && j<i)
	{
		p = p->next;
		++j;
	}
	if (!p)
		return;     /*第i个结点不存在*/
	s = (LinkList)malloc(sizeof(Node));
	s->data = e;
	s->next = p->next;
	p->next = s;
}

/*删除L的第i个元素,用e返回其值,L的长度减1*/
void ListDelete(LinkList *L, int i, ElemType *e)
{
	LinkList p, q;
	p = *L;
	int j;
	j = 1;
	while (p->next && j<i)
	{
		p = p->next;
		++j;
	}
	if (!p->next)        /*没有第i个元素*/
		return;
	q = p->next;
	p->next = q->next;
	*e = q->data;
	free(q);
}

循环链表

循环链表是头尾相接的单链表。结构图示:

 或 

上图中,终端结点用【尾指针rear】指示,头结点是 rear->next,第一个结点是 rear->next->next


合并操作示例:

p = rearA->next;
rearA->next = rearB->next->next;   /*将A的尾端指向B的第一个结点(不是头结点)*/
rearB->next = p;		   /*将B的尾端指向A的头结点*/
free(p);

双向链表

双向链表就是单链表的结点中多加了一个指向前驱结点的指针。结构图示:


删除结点操作示例:

typedef struct DulNode
{
	ElemType data;
	struct DulNode *prior; /*前驱指针*/
	struct DulNode *next;  /*后继指针*/
}DulNode, *DuLinkList;

/*双向链表的删除操作*/
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值