定长顺序表与不定长顺序表

固定大小的顺序表的结构设计

固定大小的顺序表本质是一个数组,只是封装了一下,增加了一个cursize属性

#define SEQ_INIT_SIZE 10
typedef int ElemType;
struct SeqList{
	ElemType data[SEQ_INIT_SIZE];
	int cursize;
};
//或者以这种形式
typedef struct SeqList{
	ElemType data[SEQ_INIT_SIZE];
	int cursize;
}SeqList;
int main(){
	SeqList myseq;
	return 0;

内部存储图

在这里插入图片描述
此外,由于线性表的长度可变,且所需最大存储空间随问题不同而不同,则在C语言中可用动态分配的一维数组。

可变大小的顺序表的结构设计

可变大小的顺序表定义了一个指针,初始化的时候会开辟一个空间,该空间是可以修改扩容的

#define LIST_INIT_CAPACITY 10    //数组初始化大小 
#define LIST_GROW 2              //扩容倍数
typedef int ElemType;
typedef struct SeqList {
	ElemType* data; //数组起始地址 .heap
	int length; //数组总容量 
	int size; // 有效数据个数
}SeqList;

防止头文件重复引用

程序用法

//#pragma once//仅仅在这一种情况可以用,下面的具有通用性
//防止头文件被重复引用
#ifndef SEQLIST_H
#define SEQLIST_H
......
#endif

深度理解

其实“被重复引用”是指一个头文件在同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的。
比如:存在a.h文件#include "c.h"而此时b.cpp文件导入了#include “a.h” 和#include “c.h”此时就会
造成c.h重复引用。
#pragma once是编译相关,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过现在基本上已经是每个编译器都有这个定义了。
#ifndef,#define,#endif 这个是C++语言相关,这是C++语言中的宏定义,通过宏定义避免文件
多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。

头文件设计seqlist.h

//#pragma once
//防止头文件被重复引用
#ifndef SEQLIST_H
#define SEQLIST_H
#define TRUE  1
#define FALSE 0
#define OK  1
#define ERROR 0
#define OVERFLOW -1              //内存溢出 
#define LIST_INIT_CAPACITY 10    //数组初始化大小 
#define LIST_GROW 2              //扩容倍数
typedef int Status; // 状态   TRUE FALSE  
typedef int ElemType;  //数组元素类型
typedef struct SeqList {
	ElemType* data; //数组起始地址 .heap
	int length; //数组总容量 
	int size; // 有效数据个数
}SeqList;


//冒泡排序
void BubbleSort(SeqList* plist);
//二分查找(前提:数组完全有序)
int BinarySearch(SeqList* plist, ElemType val);
//将两个有序顺序表合并为1个有序的顺序表
//将pla  plb   -->  plc
void MergeList(const SeqList* pla, const SeqList* plb, SeqList* plc);
#endif

接口函数实现seqlist.cpp

#include <stdio.h>
#include <assert.h>
#include "seqlist.h"
#include <stdlib.h>

//初始化--malloc 
void initSeqList(SeqList* plist) {
	assert(plist != NULL);  //NULL: int 0
	//plist != nullptr //nullptr: (void*)0
	plist->data = (ElemType*)malloc(LIST_INIT_CAPACITY*sizeof(ElemType));
	if (plist->data == NULL) return;
	plist->length = LIST_INIT_CAPACITY; //数组初始化容量
	plist->size = 0; //有效个数
}
//销毁--data  free()   释放堆内存
void DestoryList(SeqList* plist) {
	assert(plist != NULL);
	free(plist->data);
	plist->data = NULL; // 防止野指针(悬挂指针) 如果再次free,该函数内部会检测ptr是否等于NULL,会处理防止崩溃
}
//清空  删除有效数据
void ClearList(SeqList* plist) { 
	assert(plist != NULL);
	plist->size = 0;//在这里有一定的局限性,如果是在堆区动态申请的内存 ,需要free来释放
}
//打印数组元素
void Show(SeqList* plist) {
	assert(plist != NULL);
	int n = plist->size;
	for (int i = 0; i < n; i++) {
		printf("%5d",plist->data[i]);
	}
	printf("\n");
}
//扩容操作  -- 写对  写好(效率,边界(鲁棒性))
Status Grow(SeqList* plist) {
	assert(plist != NULL);
	if (plist == NULL)  return ERROR;
	int newlength = plist->length * LIST_GROW;
	ElemType* temp = (ElemType*)realloc(plist->data,newlength*sizeof(ElemType));
	if (temp == NULL) { return OVERFLOW; }
	plist->data = temp;
	plist->length = newlength;
	return OK;
}
//判满操作
Status IsFull(SeqList* plist) {
	assert(plist != NULL); // null->  null. 崩
	return plist->size == plist->length;
}
//头插
Status InsertHead(SeqList* plist, ElemType val) {
	assert(plist != NULL);
	if (IsFull(plist) && Grow(plist) != OK) {
		return OVERFLOW;
	}
	for (int i = plist->size - 1; i >= 0; i--) {
		plist->data[i + 1] = plist->data[i];
	}
	plist->data[0] = val;
	plist->size++;
	return OK;
}
//尾插
Status InsertTail(SeqList* plist, ElemType val) {
	assert(plist != NULL);
	if (IsFull(plist) && Grow(plist) != OK) {
		return OVERFLOW;
	}
	plist->data[plist->size] = val;
	plist->size++;
	return OK;
}
//指定位置插入 pos -- 下标
Status InsertPosVal(SeqList* plist, int posindex, ElemType val) {
	assert(plist != NULL);
	if (posindex < 0 || posindex > plist->size) {
		return ERROR;
	}
	if (IsFull(plist) && Grow(plist) != OK) {
		return OVERFLOW;
	}
	//从pos后续数据向后移动  
	for (int i = plist->size - 1; i >= posindex; i--) {
		plist->data[i + 1] = plist->data[i];
	}
	plist->data[posindex] = val;
	plist->size++;
	return OK;
}
//判空操作
Status IsEmpty(SeqList* plist) {
	assert(plist != NULL);
	return plist->size == 0;
}
//头删
Status DeleteHead(SeqList* plist) {
	return DeletePos(plist,0);
}
//尾删  [1][3][]   size:1
Status DeleteTail(SeqList* plist) {
	return DeletePos(plist,plist->size-1);
}
//指定位置删除
Status DeletePos(SeqList* plist, int posindex) {
	assert(plist != NULL);
	if (IsEmpty(plist) || posindex < 0 || posindex >= plist->size)  return FALSE;
	//向前移动 覆盖前一个
	for (int i = posindex; i < plist->size; i++) {
		plist->data[i] = plist->data[i+1];
	}
	plist->size--;
	return OK;
}
//删除指定的元素  1 2 2 2 2   -> 2    剩余1
Status DeleteVal(SeqList* plist, ElemType val) {
	assert(plist != NULL);
	int index;
	while ((index = SearchVal(plist, val)) >= 0) {
		DeletePos(plist,index);
	}
	return OK;
}
//查询某个元素返回下标
int SearchVal(SeqList* plist, ElemType val) {
	assert(plist != NULL);
	int index = -1;
	for (int i = 0; i < plist->size; i++) {
		if (plist->data[i] == val) {
			index = i;
			break;
		}
	}
	return index;
}
//冒泡排序
void BubbleSort(SeqList* plist) {
	int len = plist->size;
	bool flag;
	for (int i = len-1; i>=0; i--) {
		flag = false;
		for (int j = 0; j < i; j++) {
			if (plist->data[j + 1] < plist->data[j]) {
				ElemType temp = plist->data[j + 1];
				plist->data[j + 1] = plist->data[j];
				plist->data[j] = temp;
				flag = true;
			}
		}
		if (!flag) {
			break;
		}
	}
}

//二分查找(前提:数组完全有序) --    非递归
//时间复杂度O(logN)
//空间复杂度O(1)
int BinarySearch(SeqList* plist, ElemType val) {
	//BubbleSort(plist);
	int len = plist->size;
	int i = 0, j = len - 1;
	while (i <= j) {
		int mid = i + (j - i) / 2;
		if (plist->data[mid] == val)return mid;
		else if (plist->data[mid] > val)j = mid - 1;
		else i = mid + 1;
	}
	return -1;
}
int SearchSection(SeqList* plist, int left, int right, ElemType val) {
	if (left > right)return -1;
	int mid = (left + right) / 2;
	if (plist->data[mid])return mid;
	if (plist->data[mid] > val) {
		return SearchSection(plist, left, mid - 1, val);
	}
	else {
		return SearchSection(plist, mid+1,right, val);
	}
}

//二分查找(前提:数组完全有序) --   递归(自己调自己,退出条件,问题规模)
//时间复杂度O(logN)
//空间复杂度O(logN)
int BinarySearch(SeqList* plist, ElemType val) {
	assert(plist != nullptr);
	SearchSection(plist, 0, plist->size, val);
}
//将两个有序顺序表合并为1个有序的顺序表
//将pla  plb   -->  plc
void MergeList(const SeqList* pla, const SeqList* plb, SeqList* plc) {
	assert(pla != nullptr && plb != nullptr && plc != nullptr);
	int i = 0, j = 0, z = 0;
	while(i < pla->size&& j < plb->size) {
		if (pla->data[i] < plb->data[j]) {
			//plc->data[z++] = pla->data[i++];
			InsertTail(plc, pla->data[i++]);
		}
		else {
			//plc->data[z++] = plb->data[j++];
			InsertTail(plc, plb->data[j++]);
		}
	}
	if (i >= pla->size) {
		while (j<plb->size) {
			//plc->data[z++] = plb->data[j++];
			InsertTail(plc, plb->data[j++]);
		}
	}
	if (i >= pla->size) {
		while (j < plb->size) {
			//plc->data[z++] = pla->data[i++];
			InsertTail(plc, pla->data[i++]);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值