数据结构——线性表

线性表是最简单的数据结构,其主要特征有:

1、 每个线性表只有一个头元素,一个尾元素;

2、 除第一个数据元素外,每个元素都有一个直接前驱;

3、 除最后一个数据元素外,每个元素都有一个直接后继。


一、 顺序表

顺序表是用数据元素在物理上的相邻表示逻辑上的相邻。顺序表具有随机存取的特性。

用动态分配的一位数组表示顺序表如下:

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 50
typedef struct{
	ElemType *elem;
	int length;
	int listsize;
}SqList;
初始化顺序表:

Status InitList_Seq(SqList &L)
{
	L.elem = (ElemType*)malloc(LIST_NINT_SIZE*sizeof(ElemType));
	if(!L.elem)
		exit(OVERFLOW);
	L.length = 0;
	L.lisesize = LIST_INIT_SIZE;
	return OK;
}

顺序表的插入:

Status ListInsert_Seq(SqList &L, int i, ElemType e)
{
	if(i < 1 || i > L.length + 1)
		return ERROR;
	if(L.length >= L.listsize)
	{
		newbase = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
		if(!newbase)
			exit(OVERFLOW);
		L.elem = newbase;
		L.listsize += LISTINCREMENT;
	}
	q = &(L.elem(i-1));
	for(p = &(L.elem[L.length-1]); p >= q;p--)
		*(p+1) = *p;
	*q = e;
	L.length++;
	return OK;
}

顺序表的删除:

Status ListDelete_Seq(SqList &L, int i, ElemType &e)
{
	if(i < 1 || i > L.length)
		return ERROR;
	p = &L.elem[i-1];
	e = *p;
	for(q = L.elem+L.length-1; p < q; p++)
		*p = *(p+1);
	L.length--;
	return OK;
}

从以上伪码可知,在顺序表中插入或删除一个元素,需要移动多个元素。对于插入,Ei  = n/2; 对于删除, Ed =  (n-1)/2。

二、单链表

和顺序表不同,单链表是用指针来表示数据元素之间的关系。单链表的每个结点包含两个域:一个数据域,用来存储数据元素的信息;一个指针域,用来存储后续节点的位置信息。数据元素之间的逻辑关系是用指针来表示的。逻辑上相邻的数据元素,在物理上不一定是相邻的。这样的存储结构便失去了随机存取的特性。但他的优点是插入和删除结点的时候不需要移动数据元素了。

线性表的单链表存储结构

typedef struct LNode{
	ElemType data;
	struct Lnode *next;
}LNode, *LinkList;

单链表中插入一个结点:

Status ListInsert_L(LinkList &L, int i, ElemType e)
{
	p = L;
	j = 0;
	while(p && j < i-1)
	{
		p = p->next;
		j++;
	}
	if(!p || j > i-1)
		return ERROR;
	s = (LinkList)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return OK;
}

单链表中删除一个元素结点:

Status ListDelete_L(LinkList &L, int i, ElemType &e)
{
	p = L;
	j = 0;
	while(p && j < i-1)
	{
		p = p->next;
		j++;
	}
	if(!p || j > i-1)
		return ERROR;
	q = p->next;
	e = q->data;
	p->next = q->next;
	free(q);
	return OK;
}

虽然单链表中插入和删除元素不需要移动元素了,但是获取第i个元素,却需要从头开始找起:
Status GetElem_L(LinkList L, int i, ElemType &e)
{
	p = L->next; 
	j = 1;
	while(p && j < i)
	{
		p = p ->next;
		j++;
	}
	if(!p || j > i)
		return ERROR;
	e = p->data;
	return OK;
}
在没有指针的编程语言中,我们可以用一维数组来表示线性链表——静态链表:

#define MAXSIZE 100
typedef struct{
	ElemType data;
	int cur;
}component, SLinkList[MAXSIZE];

三、双向链表

由于单链表中某些操作较为复杂,例如,PriorElem的执行时间为O(n),为了克服这种单向性的缺点,可以为每个结点设置两个指针域,一个指向后续结点,一个指向前驱结点,即双向链表。

typedef struct DuLNOde{
	ElemType data;
	struct DuLNode *prior;
	struct DuLNode *next;
}DuLNode, *DuLinkList;

双向链表的特性: d->next->prior = d->prior->next = d;

四、循环链表

循环链表是另外一种链式存储结构。其特点是表中最后一个结点的指针域又指向了头结点,使整个链表形成了一个环形。从任何一个结点出发都可以遍历表中的所有结点。有的时候,在循环链表中设立尾指针比设立头指针更方便。例如,合并两个链表的时候,如果有尾指针的话,合并操作将会非常简单。

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值