数据结构和算法系列第1篇---线性表

前言

介绍数据结构和算法中最基础的一种数据结构:线性表

定义

线性表:零个或者多个数据元素的有限序列
强调定义中两个关键的点:

  • 序列:元素之间是有序的,如果元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每一个元素都有且只有一个前驱和后继。
  • 有限:计算机中处理的对象是有限的。

线性表常见操作

  • 初始化
  • 清空
  • 查找
  • 长度
  • 插入
  • 删除

线性表的顺序存储结构

定义

指的是用一段地址连续的存储单元依次存储线性表的数据元素。

顺序存储结构代码

#define MAXSIZE 20 // 存储空间初始化分配量
typedef int ElemType;
typedef struct
{
	ElemType data[MAXSIZE];
	int lenght; /*线性表的当前长度*/
}Sqlist;

顺序存储结构需要三个属性:

  • 存储空间的起始位置:数组data,它的存储位置就是存储空间的起始位置
  • 线性表的最大存储容量。
  • 线性表的当前长度。

线性表的链式存储结构

头指针和头节点的异同

在链式存储结构中会涉及到头指针和头节点的概念。
头指针:指向链表第一个节点的指针,若链表有头结点,则是指向头结点的指针。头指针具有标识作用,所以常用头指针冠以链表的名字。无论链表是否为空,头指针均不为空,头指针是链表的必要元素。
头结点:一般命名为DummyNode,是为了操作的统一和方便设立的,放在第一元素的节点之前。其数据域一般无意义(也可以存放链表的长度)。有了头结点,对在第一元素节点前插入节点和删除第一节点,其操作和其他节点的操作就统一了。头节点不一定是链表的必要元素。

链式存储结构代码

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

常见操作代码,建议记忆

读取节点

// 单链表的读取
Satus GetElement(LinkedList L,int i, ElemType *e)
{
	int j;
	LinkedList  p; // 声明一个节点p
	p = L; // L为头指针
	j = 1; // j为计数器
	while (p && j < i)
	{
		p = p->next;
		j++;
	}
	if (!p || j  > i)
	{
		return ERROR;
	}
	*e = p->data;
	return OK;
}

插入节点

// 单链表插入标准语句:s->next = p->next; p->next = s;
Status ListInsert (LinkedLsit L,int i, ElemetType e)
{
 	int j; // 计数器
 	LinkedList p,s
 	p = L;
 	j = 1;
 	while (p  && j < i)
 	{
		p = p->next;
		j++;
	}
	if (!p || j > i)
	{
		return ERROR;
	}
	s = malloc(sizeof (Node));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return OK;
}

删除某个节点

// 单链表删除标准语句:q = p->next; p->next = q->next;
Status ListDelet(LinkedList L, int i,ElemType* e)
{
	int j; // 计数器
	LinkedList p ,q;
	p = L; // L为头指针
	j = 1;
	while (p && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (!p || j > i - 1)
	{
		return ERROR;
	}
	q = p->next;
	p->next = q->next;
	*e = q->data;
	free(q);
	return OK;
}

创建整个链表

// 头插
/*
	标准语句:
	loop
	{
	   p = malloc();
		p->next = L->next;
		L->next = p;
	}
*/
void CreatListHead(LinkedList L, int n)
{
	LinkedList p;
	int i;
	L = malloc(sizeof(Node)); // 创建头结点
	L->next = NULL;
	for( i = 0; i < n ; i++)
	{
		p = malloc(sizeof (Node)); // 生成新节点
		p->data = rand() % 100; 
		p->next = L->next;
		L->next = p; // 插入到表头
	}
	
}

// 尾插
/*
	标准语句
	loop
	{
		p = malloc(); //  生成新的节点
		r->next = p;
		r = p;
	}
*/
void CreatListTail(LinkedList L, int n)
{
	LinkedList p , r;
	int i;
	L= malloc(sizeof (Node));
	r = L;
	for (i = 0;i < n; i++)
	{
		p = malloc(sizeof (Node));
		p->data = rand() % 100; 
		r->next = p;
		r = p;
	}
	r->next = NULL;
}

删除整个链表

/*
标准语句
q = p->next; // 在释放p之前,一定要先将他的后继节点找到
free(p);
p = q;
*/
Status ClearList(LinkedList L)
{
	LinkdeList p ,q
	p = L; // L为头指针
	while (p)
	{
		q = p->next;
		free(p);
		p = q;
	}
}

链式结构和顺序结构的优缺点对比——建议记忆

  • 存储分配方式
    顺序存储结构用一段连续的存储单元存储数据元素
    链表采用链式存储结构,存储单元不是连续的。
  • 时间性能
    查找
    顺序存储结构:O(1)
    链表 O(n)
    插入&删除:
    顺序存储结构:O(n)
    链表:O(1)
  • 空间性能
    顺序存储需要预分配存储空间
    链表不需要预分配存储空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值