数据结构:线性表

p.s.个人收录用

p.ss.本文所有代码均使用c语言

目录

存储结构

顺序存储

顺序表

链式储存

单向链表

双向链表

循环单链表

循环双链表


如果一个数据元素序列满足以下要求:
1.第一个数据前没有数据,最后一个数据后面没有数据
2.除去最前面和最后面两个数据,其他数据都有唯一的前驱数据 和唯一的后继数据
称 这些数据组成的结构是线性结构,其构成了线性表
也说 这些数据之间的逻辑关系是线性的

存储结构

顺序存储

组成:数组=>顺序表
优点:随机存取
缺点:插入&删除需要大量操作,可能会空间浪费
应用场景:随机查看的操作较多,且修改操作较少

顺序表

结构体组成:数组(存储数据) +  理论容量 + 实际容量

typedef struct arraylist
{
	int* data;//指针模拟开数组
	int length;//理论容量
	int size;//实际容量
}MyArr;
//初始化
MyArr initArray(int n)
{
	MyArr ar;
	ar.data = (int*)malloc(sizeof(int) * n);
	if (ar.data == NULL)
		printf("空间分配失败\n");
	ar.length = n;
	ar.size = 0;
	return ar;
}

 操作:增 插 删 改 查

 1) 增加:在末尾添加一个元素 (p.s. 首先判断是否超限)

//增加
void add(MyArr* a, int k)
{
	if (a->size < a->length)//判断是否超限
	{
		a->data[a->size] = k;
		a->size++;
	}
	else
		printf("空间已满\n");
}

2) 插入:在指定位置插入一个元素

//插入
void insert(MyArr* a, int i, int k)
{
	if (a->size < a->length)//判断是否超限
	{
		for (int j = a->size - 1; j >= i; j--)//移动位置(倒着移)
			a->data[j + 1] = a->data[j];
		a->data[i] = k;//插入赋值
		a->size++;
	}
	else
		printf("空间已满\n");
}

3) 删除:删除指定数据k
                首先,查找
                其次,删除

//查找
int find(MyArr a, int k)
{
	for (int i = 0; i < a.size; i++)
		if (a.data[i] == k)
			return i;
	return -1;
}

//删除
void del(MyArr* a, int k)
{
	int i = find(*a, k);
	if (i == -1)
		printf("不存在该数据\n");
	else
	{
		for (int j = i; j < a->size - 1; j++)
			a->data[j] = a->data[j + 1];
		a->size--;
	}
}

4) 修改:把指定位置的元素改成另一个元素 

//修改
void change(MyArr* a, int i, int k)
{
	a->data[i] = k;
}
链式储存

组成:链表(由若干个结点组成)
分类:单向链表 双向链表 循环链表 空链表
相关概念:
        结点 / 节点:数据 + 下一个数据的地址(指向下一个数据的指针)
        头指针:存储第一个结点的地址的指针,可标记一个链表
        首元结点:第一个存储真实数据的结点(非空链表一定有)
        头结点:链表中第一个没有存储真实数据的结点(可有可无)
作用: 1)当不带头结点时,对首元结点的操作需要涉及头指针,非常特殊
                 带头结点时,首元结点与其他结点无异
            2)对空链表:带头结点,空链表和非空链表都有结点
声明链表 = 声明结点
应用场景:1)可以实现各种各样的数据结构,灵活
缺点:不能随机访问

单向链表

 结构体组成:数据域data + 指针域next(下一个数据的地址)

typedef struct ListNode {
	int data;//数据
	struct ListNode* next;//保存下一个结点的地址
}Node, * linklist;

p.s.声明头指针 => 增强可读性 

//初始化
linklist initlist()
{
	linklist l = (Node*)malloc(sizeof(Node));
	if (l == NULL)
		printf("分配失败\n");
	else
		l->next = NULL;
	return l;
}

 操作:增 插 删 改 查

1) 增加:
            不带头结点的链表:在首元节点前插入一个结点——动头指针;在其他结点前插入结点;
            带头结点的链表:不分类

接下来以带头结点的链表为例:

步骤:1) 把数据放到一个链表中;2) 再把结点插入到链表中;

①头插

//头插
linklist head_insert(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		s->next = head->next;
		head->next = s;
	}
	return head;
}

②尾插

//尾插
linklist tail_insert(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		s->next = NULL;
		//先找到最后一个结点
		Node* t = head;
		while (t != NULL)
		{
			if (t->next == NULL)
				break;
			else
				t = t->next;
		}
		//插入
		t->next = s;
	}
	return head;
}

 ③中间插

//中间插
linklist mid_insert(linklist head, int x, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		//先找到x所在的结点
		Node* t = head->next;//比较数据,故从首元节点开始比较
		while (t->data != x)
			t = t->next;
		//插入
		s->next = t->next;
		t->next = s;
	}
	return head;
}

2) 删除:删除指定数据k
                首先,查找
                其次,删除

//删除:删除数据k
linklist del(linklist head, int k)
{
	Node* t = head->next;
	Node* p = head;
	while (t->data != k)
	{
		t = t->next;
		p = p->next;
	}
	p->next = t->next;
	t->next = NULL;//可有可无
	free(t);//把t的空间回收;释放空间
	t = NULL;
	return head;
}

 3) 修改:把指定位置的元素改成另一个元素

//修改
linklist change(linklist head, int k, int x)
{
	Node* t = head->next;
	while (t->data != k)
		t = t->next;
	t->data = x;
}
双向链表

 结构体组成:数据域data + 指针域pre(上一个数据的地址)+  指针域next(下一个数据的地址)

typedef struct ListNode {
	struct ListNode* pre;//上一个结点的地址
	int data;
	struct ListNode* next;
}Node, * linklist;
//初始化
linklist initlist()
{
	linklist l = (Node*)malloc(sizeof(Node));
	if (l == NULL)
		printf("分配失败\n");
	else
	{
		l->pre = NULL;
		l->next = NULL;
	}
	return l;
}

 操作:增 插 删 改 查

1) 增加:

接下来以带头结点的链表为例:

①头插

//头插
linklist head_insert(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		s->next = head->next;
		s->pre = head;
		if (s->next!=NULL)
			head->next->pre = s;
		head->next = s;
	}
	return head;
}

②尾插

//尾插
linklist tail_insert(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		s->next = NULL;
		Node* t = head;
		while (t != NULL)
		{
			if (t->next == NULL)
				break;
			t = t->next;
		}
		t->next = s;
		s->pre = t;
	}
	return head;
}

 ③中间插

//中间插
linklist mid_insert(linklist head, int x, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		Node* t = head;
		while (t != NULL && t->data != x)
			t = t->next;
		s->next = t->next;
		s->pre = t;
		t->next->pre = s;
		t->next = s;
	}
	return head;
}

2) 删除:删除指定数据k
                首先,查找
                其次,删除

//删
linklist del(linklist head, int x)
{
	Node* t = head->next;
	while (t != NULL && t->data != x)
		t = t->next;
	t->pre->next = t->next;
	if (t->next != NULL)
		t->next->pre = t->pre;
	t->pre = NULL;
	t->next = NULL;
	free(t);
	t = NULL;
	return head;
}

 3) 修改:把指定位置的元素改成另一个元素

//改
linklist change(linklist head, int x, int x0)
{
	Node* s = head->next;
	while (s != NULL && s->data != x)
		s = s->next;
	s->data = x0;
}
循环单链表

 结构体组成:数据域data + 指针域next(下一个数据的地址)

typedef struct NodeList {
	int data;
	struct NodeList* next;
}Node, * linklist;
//初始化
linklist init()
{
	linklist l = (Node*)malloc(sizeof(Node));
	if (l == NULL)
		printf("分配失败\n");
	else
		l->next = l;
	return l;
}

 操作:增 插 删 改 查

1)增加

//头插
linklist insert_head(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("分配失败\n");
	else
	{
		s->data = k;
		s->next = head->next;
		head->next = s;
	}
	return head;
}
//尾插
linklist insert_tail(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("失败\n");
	else
	{
		s->data = k;
		s->next = head;
		Node* t = head;
		while (t != NULL)
		{
			if (t->next == head)
				break;
			t = t->next;
		}
		t->next = s;
	}
	return head;
}
//中间插
linklist insert_mid(linklist head, int x, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("失败\n");
	else
	{
		s->data = k;
		Node* t = head;
		while (t != NULL)
		{
			if (t->data == x)
				break;
			t = t->next;
		}
		s->next = t->next;
		t->next = s;
	}
	return head;
}

2)删除

//删除
linklist del(linklist head, int k)
{
	Node* t = head->next;
	Node* p = head;
	while (t != NULL)
	{
		if (t->data == k)
			break;
		t = t->next;
		p = p->next;
	}
	p->next = t->next;
	t->next = NULL;
	free(t);
	t = NULL;
	return head;
}

3)改变

//改变
linklist change(linklist head, int x, int k)
{
	Node* t = head->next;
	while (t != NULL)
	{
		if (t->data == x)
			break;
	}
	t->data = k;
	return head;
}
循环双链表

  结构体组成:数据域data + 指针域pre(上一个数据的地址)+  指针域next(下一个数据的地址)

typedef struct NodeList {
	struct NodeList* pre;
	int data;
	struct NodeList* next;
}Node, * linklist;
//初始化
linklist init()
{
	linklist l = (Node*)malloc(sizeof(Node));
	if (l == NULL)
		printf("失败\n");
	else
	{
		l->pre = l;
		l->next = l;
	}
	return l;
}

  操作:增 插 删 改 查

1)增加

//头插
linklist insert_head(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("失败\n");
	else
	{
		s->data = k;
		s->next = head->next;
		s->pre = head;
		head->next->pre = s;
		head->next = s;
	}
	return head;
}
//尾插
linklist insert_tail(linklist head, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("失败\n");
	else
	{
		s->data = k;
		s->next = head;
		s->pre = head->pre;
		head->pre->next = s;
		head->pre = s;
	}
	return head;
}
//中间插
linklist insert_mid(linklist head, int x, int k)
{
	Node* s = (Node*)malloc(sizeof(Node));
	if (s == NULL)
		printf("失败\n");
	else
	{
		s->data = k;
		Node* t = head;
		while (t != NULL)
		{
			if (t->data == x)
				break;
			t = t->next;
		}
		s->pre = t;
		s->next = t->next;
		t->next->pre = s;
		t->next = s;
	}
	return head;
}

2)删除

//删除
linklist del(linklist head, int x)
{
	Node* t = head->next;
	while (t != NULL)
	{
		if (t->data == x)
			break;
		t = t->next;
	}
	t->pre->next = t->next;
	t->next->pre = t->pre;
	t->next = NULL;
	t->pre = NULL;
	free(t);
	t = NULL;
	return head;
}

3)改变

//改变
linklist change(linklist head, int x, int k)
{
	Node* t = head->next;
	while (t != NULL)
	{
		if (t->data == x)
			break;
	}
	t->data = k;
	return head;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值