【数据结构|线性表】线性表所有基本操作总结(严蔚敏数据结构)

0、介绍

    本文基本涵盖了线性表的所有基本操作,与严蔚敏数据结构内容大致贴合,且大部分函数取名结合STL,可结合来学习,可直接最后跳转完整代码复制,代码运行没问题(截图省了)有问题欢迎交流。
    此节重点应该就是合并了,算法思路可目录跳转

一、详细操作实现(代码)

1.00 结构体定义

typedef struct SeqList {
	ElemType* base;  //存储空间首地址
	int capacity;  //容量
	int size;  //当前长度
}SeqList;

1.0 初始化

  • 为存储空间首地址分配内存空间
  • 确定容量(提前定义好);
  • 确定目前长度(初始化记为0)
void InitSeqList(SeqList* list)
{
	list->base = (ElemType*)malloc(sizeof(SeqList) * SEQLIST_INIT_SIZE);
	assert(list->base != NULL);
	list->capacity = SEQLIST_INIT_SIZE;
	list->size = 0;
}

1.1 顺序表表尾插入数

  • 确定空间是否满!!!
  • 尾插
void push_back(SeqList* list, ElemType x)
{
	if (list->size == list->capacity)
		printf("顺序表空间已满,%d不能尾部插入数据.\n", x);
	list->base[list->size] = x;
	list->size++;
}

1.2 顺序表表头插入数

  • 判断满没满
  • 先移动否则覆盖原有元素,且从最后一个开始(画图理解)
  • 表头插入元素,长度加一
void push_front(SeqList* list, ElemType x)
{
	//头插那需要确保顺序表不为满
	if (list->size == list->capacity)
		printf("顺序表空间已满,%d不能头部插入数据.\n", x);
	int i = list->size;
	for (; i > 0; i--)
	{
		//向后移动数据
		list->base[i] = list->base[i - 1];
	}
	list->base[0] = x;
	//确保插入后目前长度加一
	list->size++;
}

1.3 展示顺序表

循环即可

void show_list(SeqList* list)
{
	int i;
	for (i = 0; i < list->size; i++)
	{
		printf("%d ", list->base[i]);
	}
	printf("\n");
}

1.4 尾部删除数据

  • 判断不为空,不然没的删
  • 只看当前长度size,所以修改即可不需内存操作(盖起来看不见就行)
void pop_back(SeqList* list)
{
	//判断不能为空
	if (list->size == 0)
	{
		printf("顺序表已空,不能尾部删除数据.\n");
		return;
	}
	//原元素在但是长度减少无法使用到,没必要内存删除
	list->size--;
}

1.5 头部删除数据

联想下头插

  • 判空
  • 移动
  • 长度减一
void pop_front(SeqList* list)
{
	//判断不能为空
	if (list->size == 0)
	{
		printf("顺序表已空,不能头部删除数据.\n");
		return;
	}
	int i = 0;
	for (; i < list->size - 1; i++)
	{
		//左移数据
		list->base[i] = list->base[i + 1];
	}
	list->size--;
}

1.6 指定位置插入

  • 判断合不合理,不合理结束多省事
  • 类似头插(本来要考虑特殊情况头和尾,但是都满足)
void insert_pos(SeqList* list, ElemType x, int pos)
{
	//判断插入位置是否合理
	if (pos<0 || pos>list->capacity)
	{
		printf("插入数据的位置非法,不能插入数据.\n");
		return;
	}
	if (list->size >= list->capacity)
	{
		printf("顺序表空间已满,%d不能按位置插入数据.\n", x);
		return;
	}
	//类似头插
	for (int i = list->size; i > pos; --i)
	{
		list->base[i] = list->base[i - 1];
	}
	list->base[pos] = x;
	list->size++;
}

1.7 查找元素所在位置,没有返回-1

  • 循环查找即可
  • 代码中找到就返回,故只能找到第一次出现
int find(SeqList* list, ElemType x)
{
	//只能查找第一次出现的位置
	for (int i = 0; i < list->size; i++)
	{
		if (list->base[i] == x)
			return i;
	}
	return -1;
}

1.8 返回长度

理解结构体的话就没必要贴代码吧,没懂就额。。。

1.9 指定下标删除

  • 还是判断
  • 类似头删
void delete_pos(SeqList* list, int pos)
{
	if (pos < 0 || pos >= list->size)
	{
		printf("删除数据的位置非法,不能删除数据.\n");
		return;
	}
	//左移
	for (int i = pos; i < list->size - 1; ++i)
	{
		list->base[i] = list->base[i + 1];
	}
	list->size--;
}

1.10 删除某个指定元素

  • 没find函数就循环找,找到再指定删
  • find有了位置,指定删更简单,找不到返回
void delete_val(SeqList* list, ElemType val)
{
	/*
	for (int i = 0; i < list->size; i++)
	{
		if (list->base[i] == val)
		{
			for (int j = i; j < list->size - 1; j++)
			{
				list->base[j] = list->base[j + 1];
			}
			list->size--;
		}
	}
	*/
	//简易版
	int pos = find(list, val);
	if (pos == -1)
	{
		printf("要删除的数据不存在.\n");
		return;
	}
	delete_pos(list, pos);
}

1.11 排序

用的冒泡,挺好理解应该,外侧循环每轮出个大泡泡

void sort(SeqList* list)
{
	for (int i = 0; i < list->size - 1; i++)
	{
		for (int j = 0; j < list->size - i - 1; j++)
		{
			if (list->base[j] > list->base[j + 1])
			{
				ElemType temp = list->base[j];
				list->base[j] = list->base[j + 1];
				list->base[j + 1] = temp;
			}
		}
	}
}

1.12 反转

  • 判断 0 1没得转
  • 定义个头和尾碰到结束
void reverse(SeqList* list)
{
	//先判断长度,为0为1不用反转
	if (list->size == 0 || list->size == 1)
		return;
	int low = 0;
	int high = list->size - 1;
	ElemType tmp;
	while (low < high)
	{
		tmp = list->base[low];
		list->base[low] = list->base[high];
		list->base[high] = tmp;

		low++;
		high--;
	}
}

1.13 清空

不是销毁就不要管内存先

void clear(SeqList* list)
{
	list->size = 0;
}

1.14 销毁

清了首部地址,其他也都置0就行

void destroy(SeqList* list)
{
	free(list->base);
	list->base = NULL;
	list->capacity = 0;
	list->size = 0;
}

重点 1.15 合并

都是归并思路,总有一个先弄完

void mergeSeq(SeqList* la, SeqList* lb, SeqList* lc)
{
	/*
	* 方法1:课本
	//分别记录la lb首地址
	ElemType* pa = la->base;
	ElemType* pb = lb->base;

	lc->size = la->size + lb->size;
	ElemType* pc = lc->base = (ElemType*)malloc(sizeof(SeqList) * lc->size);

	//分别记录la lb尾地址
	ElemType* pa_last = la->base + la->size - 1;
	ElemType* pb_last = lb->base + lb->size - 1;
	//归并,小的放进pc
	while (pa <= pa_last && pb<=pb_last)
	{
		if (*pa < *pb)
			*pc++ = *pa++;
		else
			*pc++ = *pb++;
	}
	//剩下的
	while(pa <= pa_last)*pc++ = *pa++;
	while(pb <= pb_last)*pc++ = *pb++;
	*/

	//方法2:
	lc->capacity = la->size + lb->size;
	lc->base = (ElemType*)malloc(sizeof(SeqList) * lc->capacity);

	int ia = 0;
	int ib = 0;
	int ic = 0;

	while (ia < la->size && ib < lb->size)
	{
		if (la->base[ia] < lb->base[ib])
			lc->base[ic++] = la->base[ia++];
		else
			lc->base[ic++] = lb->base[ib++];
	}
	while (ia < la->size)lc->base[ic++] = la->base[ia++];
	while (ib < lb->size)lc->base[ic++] = lb->base[ib++];

	lc->size = la->size + lb->size;//实时长度
}

二、完整代码

3.1 .h头文件

#pragma once

#include<stdio.h>
#include<malloc.h>
#include <assert.h>
#include<Windows.h>

#define SEQLIST_INIT_SIZE 8

typedef int ElemType;  //给int取别名

typedef struct SeqList {
	ElemType* base;  //存储空间首地址
	int capacity;  //容量
	int size;  //当前长度
}SeqList;

//0.初始化
void InitSeqList(SeqList* list);

//1.顺序表表尾插入数
void push_back(SeqList* list, ElemType x);

//2.顺序表表头插入数
void push_front(SeqList* list, ElemType x);

//3.展示顺序表
void show_list(SeqList* list);

//4.尾部删除数据
void pop_back(SeqList* list);

//5.头部删除数据
void pop_front(SeqList* list);

//6.指定位置插入
void insert_pos(SeqList* list, ElemType x, int pos);

//7.查找元素所在位置,没有返回-1
int find(SeqList *list, ElemType x);

//8.返回长度 ?
int length(SeqList* list);

//9.指定下标删除
void delete_pos(SeqList* list, int pos);

//10.删除某个指定元素
void delete_val(SeqList* list,ElemType val);

//11.排序
void sort(SeqList* list);

//12.反转
void reverse(SeqList* list);

//13.清空
void clear(SeqList* list);

//14.销毁
void destroy(SeqList* list);

//15.合并
void mergeSeq(SeqList* la, SeqList* lb, SeqList* lc);

3.2 Main.cpp 文件

#include"SeqList.h"

//排序实验主函数
int main()
{
	SeqList la, lb, lc;
	InitSeqList(&la);
	InitSeqList(&lb);
	InitSeqList(&lc);

	push_front(&la, 10);
	push_front(&la, 1);
	push_front(&la, 2);
	push_front(&la, 4);
	push_front(&la, 6);
	show_list(&la);

	push_back(&lb, 8);
	push_back(&lb, 23);
	push_back(&lb, 12);
	push_back(&lb, 67);
	push_back(&lb, 78);
	show_list(&lb);

	mergeSeq(&la, &lb, &lc);
	//sort(&lc);
	show_list(&lc);
	return 0;
}
/*
* 1-14函数实现
int main()
{
	SeqList mylist;
	InitSeqList(&mylist);

	ElemType Item = 3;
	int pos = 2;
	int select = 1;
	while (select)
	{
		printf("**************************************\n");
		printf("* [1]  push_back    [2]  push_front  *\n");
		printf("* [3]  show_list    [4]  pop_back    *\n");
		printf("* [5]  pop_front    [6]  insert_pos  *\n");
		printf("* [7]  find         [8]  length      *\n");
		printf("* [9]  delete_pos   [10] delete_val  *\n");
		printf("* [11] sort         [12] resver      *\n");
		printf("* [13] clear        [14] destroy     *\n");
		printf("* [0]  quit_system                   *\n");
		printf("**************************************\n");
		printf("请选择:>");
		scanf_s("%d", &select);
		if (select == 0)
			break;
		switch (select)
		{
		case 1:
			printf("请输入要插入的数据(-1结束):>");
			while (scanf_s("%d", &Item), Item != -1)
			{
				push_back(&mylist, Item);
			}
			break;
		case 2:
			printf("请输入要插入的数据(-1结束):>");
			while (scanf_s("%d", &Item), Item != -1)
			{
				push_front(&mylist, Item);
			}
			break;
		case 3:
			show_list(&mylist);
			break;
		case 4:
			pop_back(&mylist);
			break;
		case 5:
			pop_front(&mylist);
			break;
		case 6:
			printf("请输入要插入数据:>");
			scanf_s("%d", &Item);
			printf("请输入要插入的位置:>");
			scanf_s("%d", &pos);
			insert_pos(&mylist, Item, pos);
			break;
		case 7:
			printf("请输入要查找的数据:>");
			scanf_s("%d", &Item);
			pos = find(&mylist, Item);
			if (pos == -1)
				printf("查找的数据%d在顺序表中不存在.\n", Item);
			else
				printf("查找的数据%d在顺序表中的%d下标位置.\n", Item, pos);
			break;
		case 8:
			length(&mylist);
			break;
		case 9:
			printf("请输入要删除数据的下标:>");
			scanf_s("%d", &pos);
			delete_pos(&mylist, pos);
			break;
		case 10:
			printf("请输入要删除的数据:>");
			scanf_s("%d", &Item);
			delete_val(&mylist, Item);
			break;
		case 11:
			printf("排序前顺序表:\n");
			show_list(&mylist);
			sort(&mylist);
			printf("排序后顺序表:\n");
			show_list(&mylist);
			break;
		case 12:
			printf("反转前顺序表:\n");
			show_list(&mylist);
			reverse(&mylist);
			printf("反转后顺序表:\n");
			show_list(&mylist);
			break;
		case 13:
			clear(&mylist);
			break;
		case 14:
			destroy(&mylist);
			break;
		default:
			printf("输入的选择错误,请重新输入.\n");
			break;
		}
	}
	return 0;
}
*/

3.3 .cpp实现源文件

#include"SeqList.h"

void InitSeqList(SeqList* list)
{
	list->base = (ElemType*)malloc(sizeof(SeqList) * SEQLIST_INIT_SIZE);
	assert(list->base != NULL);
	list->capacity = SEQLIST_INIT_SIZE;
	list->size = 0;
}

void push_back(SeqList* list, ElemType x)
{
	if (list->size == list->capacity)
		printf("顺序表空间已满,%d不能尾部插入数据.\n", x);
	list->base[list->size] = x;
	list->size++;
}

void push_front(SeqList* list, ElemType x)
{
	//头插那需要确保顺序表不为满
	if (list->size == list->capacity)
		printf("顺序表空间已满,%d不能头部插入数据.\n", x);
	int i = list->size;
	for (; i > 0; i--)
	{
		//向后移动数据
		list->base[i] = list->base[i - 1];
	}
	list->base[0] = x;
	//确保插入后目前长度加一
	list->size++;
}

void show_list(SeqList* list)
{
	int i;
	for (i = 0; i < list->size; i++)
	{
		printf("%d ", list->base[i]);
	}
	printf("\n");
}

void pop_back(SeqList* list)
{
	//判断不能为空
	if (list->size == 0)
	{
		printf("顺序表已空,不能尾部删除数据.\n");
		return;
	}
	//原元素在但是长度减少无法使用到,没必要内存删除
	list->size--;
}

void pop_front(SeqList* list)
{
	//判断不能为空
	if (list->size == 0)
	{
		printf("顺序表已空,不能头部删除数据.\n");
		return;
	}
	int i = 0;
	for (; i < list->size - 1; i++)
	{
		//左移数据
		list->base[i] = list->base[i + 1];
	}
	list->size--;
}

void insert_pos(SeqList* list, ElemType x, int pos)
{
	//判断插入位置是否合理
	if (pos<0 || pos>list->capacity)
	{
		printf("插入数据的位置非法,不能插入数据.\n");
		return;
	}
	if (list->size >= list->capacity)
	{
		printf("顺序表空间已满,%d不能按位置插入数据.\n", x);
		return;
	}
	//类似头插
	for (int i = list->size; i > pos; --i)
	{
		list->base[i] = list->base[i - 1];
	}
	list->base[pos] = x;
	list->size++;
}

int find(SeqList* list, ElemType x)
{
	//只能查找第一次出现的位置
	for (int i = 0; i < list->size; i++)
	{
		if (list->base[i] == x)
			return i;
	}
	return -1;
}

int length(SeqList* list)
{
	return list->size;
}

void delete_pos(SeqList* list, int pos)
{
	if (pos < 0 || pos >= list->size)
	{
		printf("删除数据的位置非法,不能删除数据.\n");
		return;
	}
	//左移
	for (int i = pos; i < list->size - 1; ++i)
	{
		list->base[i] = list->base[i + 1];
	}
	list->size--;
}

void delete_val(SeqList* list, ElemType val)
{
	/*
	for (int i = 0; i < list->size; i++)
	{
		if (list->base[i] == val)
		{
			for (int j = i; j < list->size - 1; j++)
			{
				list->base[j] = list->base[j + 1];
			}
			list->size--;
		}
	}
	*/
	//简易版
	int pos = find(list, val);
	if (pos == -1)
	{
		printf("要删除的数据不存在.\n");
		return;
	}
	delete_pos(list, pos);
}

void sort(SeqList* list)
{
	for (int i = 0; i < list->size - 1; i++)
	{
		for (int j = 0; j < list->size - i - 1; j++)
		{
			if (list->base[j] > list->base[j + 1])
			{
				ElemType temp = list->base[j];
				list->base[j] = list->base[j + 1];
				list->base[j + 1] = temp;
			}
		}
	}
}

void reverse(SeqList* list)
{
	//先判断长度,为0为1不用反转
	if (list->size == 0 || list->size == 1)
		return;
	int low = 0;
	int high = list->size - 1;
	ElemType tmp;
	while (low < high)
	{
		tmp = list->base[low];
		list->base[low] = list->base[high];
		list->base[high] = tmp;

		low++;
		high--;
	}
}

void clear(SeqList* list)
{
	list->size = 0;
}

void destroy(SeqList* list)
{
	free(list->base);
	list->base = NULL;
	list->capacity = 0;
	list->size = 0;
}

void mergeSeq(SeqList* la, SeqList* lb, SeqList* lc)
{
	/*
	* 方法1:课本
	//分别记录la lb首地址
	ElemType* pa = la->base;
	ElemType* pb = lb->base;

	lc->size = la->size + lb->size;
	ElemType* pc = lc->base = (ElemType*)malloc(sizeof(SeqList) * lc->size);

	//分别记录la lb尾地址
	ElemType* pa_last = la->base + la->size - 1;
	ElemType* pb_last = lb->base + lb->size - 1;
	//归并,小的放进pc
	while (pa <= pa_last && pb<=pb_last)
	{
		if (*pa < *pb)
			*pc++ = *pa++;
		else
			*pc++ = *pb++;
	}
	//剩下的
	while(pa <= pa_last)*pc++ = *pa++;
	while(pb <= pb_last)*pc++ = *pb++;
	*/

	//方法2:视频
	lc->capacity = la->size + lb->size;
	lc->base = (ElemType*)malloc(sizeof(SeqList) * lc->capacity);

	int ia = 0;
	int ib = 0;
	int ic = 0;

	while (ia < la->size && ib < lb->size)
	{
		if (la->base[ia] < lb->base[ib])
			lc->base[ic++] = la->base[ia++];
		else
			lc->base[ic++] = lb->base[ib++];
	}
	while (ia < la->size)lc->base[ic++] = la->base[ia++];
	while (ib < lb->size)lc->base[ic++] = lb->base[ib++];

	lc->size = la->size + lb->size;//实时长度
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝冰红茶的方舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值