DS-顺序表的基本操作(超级齐全)

数据结构-顺序表的基本操作(C语言实现)

实现的具体功能如下:

  1. 初始化顺序表
  2. 显示顺序表
  3. 尾部插入数据
  4. 头部插入数据
  5. 尾部删除数据
  6. 头部删除数据
  7. 顺序表扩容
  8. 查找数据(遍历式)
  9. 二分查找数据
  10. 排序
  11. 按值插入数据
  12. 按位置插入数据
  13. 按值删除数据
  14. 按位置删除数据
  15. 删除所有(与给定值相等的)数据
  16. 清空顺序表
  17. 获取头部元素
  18. 获取尾部元素
  19. 获取顺序表长度
  20. 获取顺序表容量
  21. 逆置顺序表
  22. 摧毁顺序表

这一大堆有被吓到吗?22个功能可还行?试问还有比我更全的吗?!!
在这里插入图片描述
注:上述个别功能是不暴露给用户的,所以菜单中加上退出总共是20个选项。

源代码如下:
main.c

#include "SeqList.h"

static void Menu()
{
	printf("**************************************************\n");
	printf("**************************************************\n");
	printf("--------  Please enter your choice:       --------\n");
	printf("--------  0.Quit           1.Print        --------\n");
	printf("--------  2.PushBack       3.PushFront    --------\n");
	printf("--------  4.PopBack        5.PopFront     --------\n");
	printf("--------  6.Find           7.Sort         --------\n");
	printf("--------  8.Val_Insert     9.Pos_Insert   --------\n");
	printf("--------  10.Pos_Erase    11.Val_Erase    --------\n");
	printf("--------  12.EraseAllVal  13.Clear        --------\n");
	printf("--------  14.GetFront     15.GetBack      --------\n");
	printf("--------  16.Length       17.Capacity     --------\n");
	printf("--------  18.Reverse      19.Find_Binary  --------\n");
	printf("**************************************************\n");
	printf("**************************************************\n");
}

int main()
{
	SeqList_t list;//定义结构体变量
	InitSeqList(&list);//初始化顺序表
	ELEM_TYPE item = 0;
	size_t pos = 0;
	int select = 1;
	while (select){
		Menu();
		scanf("%d", &select);
		if (0 == select){
			printf("退出成功!\n");
			break;
		}
		switch (select){
		case 1:
			SeqListPrint(&list);
			break;
		case 2:
			printf("请输入你要插入的元素(以-1结尾): ");
			while (scanf("%d", &item), item != -1){
				SeqListPushBack(&list, item);
			}
			printf("尾部插入元素成功!\n");
			break;
		case 3:
			printf("请输入你要插入的元素(以-1结尾): ");
			while (scanf("%d", &item), item != -1){
				SeqListPushFront(&list, item);
			}
			printf("头部插入元素成功!\n");
			break;
		case 4:
			SeqListPopBack(&list);
			break;
		case 5:
			SeqListPopFront(&list);
			break;
		case 6:
			printf("请输入你要查找的数据: ");
			scanf("%d", &item);
			int ret = SeqListFind(&list, item);
			if (ret == -1){
				printf("当前顺序表为空,无法进行数据查找!\n");
			}
			else if (ret == -2){
				printf("查找数据失败,顺序表中没有该数据!\n");
			}
			else{
				printf("查找数据成功,该数据在顺序表中的下标为%d!\n", ret);
			}
			break;
		case 7:
			SeqListSort(&list);
			break;
		case 8:
			printf("请输入你要插入的数据: ");
			scanf("%d", &item);
			SeqListVal_Insert(&list, item);
			break;
		case 9:
			printf("请输入你要插入的数据和位置: \n");
			printf("数据: ");
			scanf("%d", &item);
			printf("位置: ");
			scanf("%u", &pos);
			SeqListPos_Insert(&list, pos, item);
			break;
		case 10:
			printf("请输入你要删除的数据的位置: ");
			scanf("%d", &pos);
			SeqListPos_Erase(&list, pos);
			break;
		case 11:
			printf("请输入你要删除的值: ");
			scanf("%d", &item);
			SeqListVal_Erase(&list, item);
			break;
		case 12:
			printf("请输入你要删除的值: ");
			scanf("%d", &item);
			SeqListEraseAllVal(&list, item);
			break;
		case 13:
			SeqListClear(&list);
			break;
		case 14:
			if (SeqListGetFront(&list) == -1){
				printf("当前顺序表为空,无法取表头元素!\n");
			}
			else{
				printf("该顺序表的头部元素为[%d]!\n", SeqListGetFront(&list));
			}
			break;
		case 15:
			if (SeqListGetBack(&list) == -1){
				printf("当前顺序表为空,无法取表尾元素!\n");
			}
			else{
				printf("该顺序表的尾部元素为[%d]!\n", SeqListGetBack(&list));
			}
			break;
		case 16:
			printf("该顺序表的当前长度为[%d]!\n", SeqListLength(&list));
			break;
		case 17:
			printf("该顺序表的当前容量为[%d]!\n", SeqListCapacity(&list));
			break;
		case 18:
			SeqListReverse(&list);
			break;
		case 19:
			printf("请输入你要进行查找的数据: ");
			scanf("%d", &item);
			int bin_ret = SeqListFind_Binary(&list, item);
			if (bin_ret == -1){
				printf("当前顺序表为空,无法进行数据查找!\n");
			}
			else if (bin_ret == -2){
				printf("查找数据失败,顺序表中没有该数据!\n");
			}
			else{
				printf("二分查找数据成功,该数据在顺序表中的下标为%d!\n", bin_ret);
			}
			break;
		default:
			printf("输入有误,请重新输入!\n");
			system("pause");
			system("cls");
			continue;
		}
		system("pause");
		system("cls");
	}

	DestorySeqList(&list);//摧毁顺序表

	system("pause");
	return 0;
}

SeqList.h

#ifndef _SEQLIST_H_
#define _SEQLIST_H_

#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

#pragma warning(disable:4996)

#define ELEM_TYPE int //元素类型
#define SEQLIST_DEFAULT_SIZE 8  //顺序表默认大小


typedef struct SeqList{
	ELEM_TYPE *base;//指向申请堆空间,保存元素
	size_t size;//当前元素个数
	size_t cap;//容量
}SeqList_t;

void InitSeqList(SeqList_t *plist);//初始化顺序表
void DestorySeqList(SeqList_t *plist);//摧毁顺序表
void SeqListPrint(SeqList_t *plist);//打印顺序表
void SeqListPushBack(SeqList_t *plist, ELEM_TYPE x);//尾插
void SeqListPushFront(SeqList_t *plist, ELEM_TYPE x);//头插
void SeqListPopBack(SeqList_t *plist);//尾删
void SeqListPopFront(SeqList_t *plist);//头删
int  SeqListFind(SeqList_t *plist, ELEM_TYPE x);//按值查找
void SeqListSort(SeqList_t *plist);//排序
void SeqListPos_Insert(SeqList_t *plist, size_t pos, ELEM_TYPE x);//按位置插入
void SeqListVal_Insert(SeqList_t *plist, ELEM_TYPE x);//按值插入
void SeqListPos_Erase(SeqList_t *plist, size_t pos);//按位置删除
void SeqListVal_Erase(SeqList_t *plist, ELEM_TYPE x);//按值删除
void SeqListEraseAllVal(SeqList_t *plist, ELEM_TYPE x);//删除所有值为x的数据
void SeqListClear(SeqList_t *plist);//清空顺序表
ELEM_TYPE SeqListGetFront(SeqList_t *plist);//获取头部元素
ELEM_TYPE SeqListGetBack(SeqList_t *plist);//获取尾部元素
int  SeqListLength(SeqList_t *plist);//获取长度
int  SeqListCapacity(SeqList_t *plist);//获取容量
void SeqListReverse(SeqList_t *plist);//顺序表逆置
int SeqListFind_Binary(SeqList_t *plist, ELEM_TYPE x);//二分查找数据


#endif /*_SEQLIST_H_*/

SeqList.c

#include "SeqList.h"

static void Swap(ELEM_TYPE *x, ELEM_TYPE *y)
{
	*x ^= *y;
	*y ^= *x;
	*x ^= *y;
}

void InitSeqList(SeqList_t *plist)
{
	assert(plist);
	plist->cap = SEQLIST_DEFAULT_SIZE;
	plist->base = (ELEM_TYPE *)malloc(plist->cap * sizeof(ELEM_TYPE));
	plist->size = 0;
}

static bool Inc(SeqList_t *plist, size_t new_cap)
{
	assert(plist);
	assert(new_cap > plist->cap);
	ELEM_TYPE *new_base = (ELEM_TYPE *)realloc(plist->base, sizeof(ELEM_TYPE)* new_cap);
	if (new_base == NULL){
		return false; //扩容失败
	}
	plist->base = new_base;
	plist->cap = new_cap;
	printf("顺序表已成功扩容!\n");
	return true; //扩容成功
}

static bool IsFull(SeqList_t *plist)
{
	assert(plist);
	return plist->cap == plist->size;
}

static bool IsEmpty(SeqList_t *plist)
{
	assert(plist);
	return plist->size == 0;
}

void SeqListPushBack(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsFull(plist) && !Inc(plist, plist->cap*2)){//顺序表已满且扩容失败
		printf("顺序表已满,无法继续插入!\n");
		return;
	}
	plist->base[plist->size] = x;
	plist->size++;
}

void SeqListPrint(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空!\n");
		return;
	}
	size_t i = 0;
	for (; i < plist->size; i++){
		printf("%d ", plist->base[i]);
	}
	printf("\n");
}

void SeqListPushFront(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsFull(plist) && !Inc(plist, plist->cap * 2)){
		printf("顺序表已满,无法继续插入!\n");
		return;
	}
	size_t i = plist->size;
	for (; i > 0; i--){
		plist->base[i] = plist->base[i - 1];
	}
	plist->base[0] = x;
	plist->size++;

}

void SeqListPos_Insert(SeqList_t *plist, size_t pos, ELEM_TYPE x)
{
	assert(plist);
	assert(pos >= 0);
	if (IsFull(plist) && !Inc(plist, plist->cap * 2)){
		printf("顺序表已满,无法继续插入!\n");
		return;
	}
	if (pos < 0 || pos > plist->size){
		printf("你要插入的位置非法, 无法成功插入!\n");
		return;
	}
	size_t i = plist->size;
	for (; i > pos; i--){
		plist->base[i] = plist->base[i - 1];
	}
	plist->base[pos] = x;
	plist->size++;
	printf("插入元素成功!\n");
}



void SeqListSort(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法进行排序操作!\n");
		return;
	}
	else if(plist->size == 1){
		printf("当前顺序表只有一个元素,排序操作无意义!\n");
		return;
	}

	//冒泡排序
	size_t i = 0;
	for (; i < plist->size - 1; i++){
		size_t j = 0;
		for (; j < plist->size - 1 - i; j++){
			if ((plist->base[j]) > (plist->base[j + 1])){
				Swap(&(plist->base[j]), &(plist->base[j + 1]));
			}
		}
	}
	printf("顺序表排序成功!\n");
}

void SeqListVal_Insert(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsFull(plist) && !Inc(plist, plist->cap * 2)){
		printf("顺序表已满,无法继续插入!\n");
		return;
	}
	SeqListSort(plist);//按值插入即按顺序插入,所以在插入之前顺序表必须有序
#if 0 //方法一,容易想到,但并不是最简单的做法
	size_t i = 0;
	while (i < plist->size && x > plist->base[i]){
		i++;//先找到插入数据的位置
	}
	size_t j = plist->size;
	for (; j > i; j--){
		plist->base[j] = plist->base[j - 1];//向后移动
	}
	plist->base[j] = x;	
	plist->size++;
	printf("数据插入成功!\n");
#endif
	//方法二
	size_t end = plist->size - 1;//定义一个指向顺序表尾部的"指针"
	while (end >= 0 && x < plist->base[end]){
		plist->base[end + 1] = plist->base[end];//向后移动
		end--;
	}
	plist->base[end + 1] = x;//插入数据
	plist->size++;
	printf("数据插入成功!\n");
}

void SeqListPopBack(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法继续删除!\n");
		return;
	}
	plist->size--;
	printf("尾部删除成功!\n");
}

void SeqListPopFront(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法继续删除!\n");
		return;
	}
	size_t i = 0;
	for (; i < plist->size - 1; i++){
		plist->base[i] = plist->base[i + 1];
	}
	plist->size--;
	printf("头部删除成功!\n");
}

void SeqListPos_Erase(SeqList_t *plist, size_t pos)
{
	assert(plist);
	assert(pos >= 0);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法进行删除操作!\n");
		return;
	}
	if (pos < 0 || pos >= plist->size){
		printf("你要删除的位置非法, 无法成功删除!\n");
		return;
	}
	size_t i = pos;
	for (; i < plist->size; i++){
		plist->base[i] = plist->base[i + 1];
	}
	plist->size--;
	printf("数据删除成功!\n");
}

void SeqListVal_Erase(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空, 无法进行删除操作!\n");
		return;
	}
	//有了前面已经实现的一些功能,我们只需借助某些功能就可以实现按值删除
	int pos = 0;
	pos = SeqListFind(plist, x);//先找到需要删除数据的所在位置
	if (pos == -1){
		printf("对不起,你要删除的值[%d]不存在!\n", x);
		return;
	}
	else{
		SeqListPos_Erase(plist, pos);//找到该数据所在位置后按位置删除即可
	}
}

void SeqListEraseAllVal(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法进行删除操作!\n");
		return;
	}
	size_t i = 0;
	int flag = 0;//用于检测该数据是否存在
	while (i < plist->size){
		while (x != plist->base[i] && i < plist->size){
			i++;
		}
		if (x == plist->base[i]){
			flag = 1;//如果进入过该分支,则证明找到了数据,即数据存在
			size_t j = i;
			for (; j < plist->size - 1; j++){
				plist->base[j] = plist->base[j + 1];
			}
			plist->size--;
		}
	}
	if (flag ==0 ){
		printf("对不起,你要删除的值[%d]不存在!\n", x);
		return;
	}
	printf("数据删除成功!\n");
}

int SeqListFind(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsEmpty(plist)){//空表查找操作无意义
		return -1;
	}
	size_t pos = 0;
	while (pos < plist->size && plist->base[pos] != x){
		pos++;
	}
	if (pos == plist->size){
		return -2;//表示没找到
	}
	return pos;//找到就返回该数据的下标
}

ELEM_TYPE SeqListGetFront(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		//由于插入数据的机制,表中的数据不可能有-1,因此此处逻辑可行,不过这同样也算是一个小的缺陷吧
		return -1;
	}
	return plist->base[0];
}

ELEM_TYPE SeqListGetBack(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		return -1;
	}
	return plist->base[plist->size-1];
}

int  SeqListLength(SeqList_t *plist)
{
	assert(plist);
	return plist->size;
}
int  SeqListCapacity(SeqList_t *plist)
{
	assert(plist);
	return plist->cap;
}

void SeqListReverse(SeqList_t *plist)
{
	assert(plist);
	if (IsEmpty(plist)){
		printf("当前顺序表为空,无法进行逆置操作!\n");
		return;
	}
	else if (plist->size == 1){
		printf("当前顺序表中只有一个元素,逆置操作无意义!\n");
		return;
	}
	int start = 0;
	int end = plist->size - 1;
	while (start < end){
		Swap(&(plist->base[start]), &(plist->base[end]));
		start++;
		end--;
	}
	printf("顺序表逆置成功!\n");
}

int SeqListFind_Binary(SeqList_t *plist, ELEM_TYPE x)
{
	assert(plist);
	if (IsEmpty(plist)){//空表查找操作无意义
		return -1;
	}
	SeqListSort(plist);//二分查找的前提是顺序表有序
	int start = 0;
	int end = plist->size - 1;
	int mid;
	while (start <= end){
		mid = (start + end) / 2;
		if (x > plist->base[mid]){
			start = mid + 1;
		}
		else if (x < plist->base[mid]){
			end = mid - 1;
		}
		else{
			return mid;
		}
	}
	return -2;
}

void SeqListClear(SeqList_t *plist)
{
	assert(plist);
	plist->size = 0;
	printf("顺序表已成功清空!\n");
}

void DestorySeqList(SeqList_t *plist)
{
	assert(plist);
	free(plist->base);
	plist->base = NULL;//预防野指针
	plist->size = plist->cap = 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值