文章目录
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;//实时长度
}