1. 顺序存储结构的定义
typedef struct seqence_list{
datatype *data;
int last;
int size;
}sqlist;
2 主要操作的实现
2.1 初始化
sqlist *init_sl(int size){
sqlist *sl = calloc(1, sizeof(sqlist)); // 分配顺序表
if( sl!=NULL){
sl->data = calloc(size, sizeof(datatype)); // 分配结构空间
if( sl->data == NULL){ // 分配失败,退出
free(sl);
return NULL;
}
sl->last = -1;
sl->size = size;
}
return sl;
}
2.2 判断顺序表是否满了
bool is_full(sqlist *sl) {
return sl->last == sl->size-1;
}
2.3 判断顺序表是否空的
bool is_empty(sqlist *sl) {
return sl->last == -1;
}
2.4 顺序表插入节点
- 输入: int n(插入的数据),sqlist *sl(顺序表)
- 输入:布尔型(判断插入是否成功)
bool insert_node( int n, sqlist *sl){
if (is_full(sl))
return false;
// 找到n应该插入的位置
int pos; // 插入位置
for (pos=0; pos<=sl->last; pos++){
if(n<sl->data[pos]){
break;
}
}
// 成片地移动数据
int i;
for(i=sl->last; i>=pos; i--) {
sl->data[i+1] = sl->data[i];
}
// 将n放入pos
sl->data[pos] = n;
// 更新last
sl->last++;
return true;
}
2.5 顺序表删除结点
- 输入: int n(删除的数据),sqlist *sl(顺序表)
- 输入:布尔型(判断删除是否成功)
bool remove_node( int n, sqlist *sl) {
if( is_empty(sl) ){
return false;
}
// 查找应该删除的位置
int pos;
for (pos=0; pos<=sl->last; pos++) {
if (n == sl->data[pos]){
break;
}
}
if ( pos==sl->last+1){
return false;
}
// 成片移动数据
int i;
for ( i=pos; i<sl->last; i++){
sl->data[i] = sl->data[i+1];
}
sl->last--;
return true;
}
插入或删除一个数据元素时,其时间主要耗费在移动元素上,而移动元素的个数取决于插入或删除元素的位置,所以它们的时间复杂度T=O(n)。
2.6 销毁节点
void destroy_list(sqlist *sl) {
free(sl->data);
free(sl);
}
3 顺序存储结构的特点
- 逻辑关系上相邻的两个元素在物理位置上也相邻
- 可以随机存取表中任一元素,它的存储位置可用一个简单、直观的公式来表示
- 最大的缺点就是插入和删除时需要移动大量的元素,这显然需要耗费时间。
4 练习题目
用顺序存储的方式处理正整数:输入正整数表示插入数据(比如输入3表示插入3),输入负整数表示删除数据,输入0表示退出程序。并要求:插入和删除的过程中保持该表递增有序。
#include "common.h"
#ifndef SL_NODE_TYPE
#define SL_NODE_TYPE int // 默认的节点类型是int
#endif
typedef SL_NODE_TYPE datatype;
typedef struct seqence_list{
datatype *data;
int last;
int size;
}sqlist;
// 初始化函数
sqlist *init_sl(int size){
sqlist *sl = calloc(1, sizeof(sqlist)); // 分配顺序表
if( sl!=NULL){
sl->data = calloc(size, sizeof(datatype)); // 分配结构空间
if( sl->data == NULL){ // 分配失败,退出
free(sl);
return NULL;
}
sl->last = -1;
sl->size = size;
}
return sl;
}
// 判断表是否满了
bool is_full(sqlist *sl) {
return sl->last == sl->size-1;
}
// 判断表是否空的
bool is_empty(sqlist *sl) {
return sl->last == -1;
}
//
void show_list(sqlist *sl){
if (is_empty(sl)){
return;
}
int i;
for(i=0; i<=sl->last; i++){
printf("%d ", sl->data[i]);
}
}
// 插入节点
bool insert_node( int n, sqlist *sl){
if (is_full(sl))
return false;
// 找到n应该插入的位置
int pos; // 插入位置
for (pos=0; pos<=sl->last; pos++){
if(n<sl->data[pos]){
break;
}
}
// 成片地移动数据
int i;
for(i=sl->last; i>=pos; i--) {
sl->data[i+1] = sl->data[i];
}
// 将n放入pos
sl->data[pos] = n;
// 更新last
sl->last++;
return true;
}
// 删除节点
bool remove_node( int n, sqlist *sl) {
if( is_empty(sl) ){
return false;
}
// 查找应该删除的位置
int pos;
for (pos=0; pos<=sl->last; pos++) {
if (n == sl->data[pos]){
break;
}
}
if ( pos==sl->last+1){
return false;
}
// 成片移动数据
int i;
for ( i=pos; i<sl->last; i++){
sl->data[i] = sl->data[i+1];
}
sl->last--;
return true;
}
// 销毁节点
void destroy_list(sqlist *sl) {
free(sl->data);
free(sl);
}
int main(void){
// 1. 初始化一个空的顺序表
sqlist *sl = init_sl(1000);
if(sl == NULL){
printf("初始化顺序表失败\n");
exit(0);
}
// 2. 循环地放入、删除数据
int n;
while(1) {
scanf("%d", &n);
//出入节点
if(n>0){
if(insert_node(n, sl))
show_list(sl); // 将顺序表中的所有元素列出来
else
printf("插入节点失败\n");
}
// 删除节点
if(n<0){
if( remove_node(-n, sl) )
show_list(sl); //
else
printf("无此节点\n");
}
// 退出
if(n==0) {
break;
}
}
// // 3. 销毁顺序表
// destroy_sl(sl) ;
return 0;
}
代码引用常用头文件,如果报错可以参考另外一篇常用头文件 - common.h