实验1 顺序表的实现

此讲为线性表的顺序结构实现方式

目录

顺序表的描述

1.初始化线性表

2.插入操作

3.删除操作

4.判定线性表为空或满

5.查找元素

6.输出元素

7.清空线性表


顺序表的描述

用结构体来描述顺序表,结构体中包括表的大小、存放数据的数组、表的最大容量三个数据属性。

方法1:(下面都是基于此实现)

typedef struct SQ_LIST{
    DATA_TYPE *data; 
    int maxSize;
    int count;
}LIST;

方法2:集合运算是基于此实现的

typedef struct SQ_LIST{
    DATA_TYPE data[maxSize];
    int count;
}LIST;

注意这两种定义方式,第一种初始化时需要动态申请空间,第二种不需要动态申请空间,因为数组名称是该数组的首地址常量。

void initList(LIST *head);                                           //初始化顺序表
void destroyList(LIST *head);                                        //销毁线性表
boolean insertListElementAt(LIST *head, int index, DATA_TYPE value); //在线性表下标为index的元素之前插入value
boolean insertListElementAt2(LIST *head, int k, DATA_TYPE value);    //在线性表第k个元素之前插入value
boolean appendListElementAtTheLastOne(LIST *head, DATA_TYPE value);  //在最后一个有效元素的后面追加一个元素
void showList(LIST list);                                            //显示线性表
void showOneElement(LIST list, int index);                           //显示线性表中的一个元素
boolean deleteListElementAt(LIST *head, int index);                  //删除线性表中下标为index的元素
boolean deleteListElementAt2(LIST *head, int k);                     //删除线性表中第k个元素
int countOfList(LIST list);                                          //查找线性表的元素个数
boolean isListEmpty(LIST list);                                      //判断线性表是否为空
boolean isListFull(LIST list);                                       //判断线性表是否为满
DATA_TYPE getListDataAt(LIST list, int index);                       //在线性表中查找下标为index的元素
DATA_TYPE getListDataAt(LIST list, int k);                           //在线性表中查找第k个元素
int getListDataBe(LIST list, int value);                             //在线性表中查找值为value的元素的下标
void clearList(LIST *head);                                          //清空线性表

1.初始化线性表

(1)直接定义一个线性表(后面其他功能的实现都是基于此方法)

//销毁线性表
void destroyList(LIST *head){  
    free(head->data);
}

//初始化顺序表
void initList(LIST *head){
    head->data = (DATA_TYPE *)malloc(sizeof(DATA_TYPE) * INIT_MAXSIZE);
    head->maxSize = INIT_MAXSIZE;
    head->count = 0;
}

void main(void){
    LIST list;

    initList(&list);
    destroyList(&list);

}

(2)定义一个指向线性表的指针

void destroyList(LIST **head){
    free((*head)->data);
    free(*head);

    (*head) = NULL;
}

void initList(LIST **head){
    if(*head != NULL){     //此处是要检测list1(若主函数传入的是list1的首地址)是否为NULL
        return;            //若为NULL,则继续向下操作
    }                       //若不为NULL,说明list1已经指向一个线性表了
    
    (*head) = (LIST *)malloc(sizeof(LIST));

    (*head)->data = (DATA_TYPE *)malloc(sizeof(DATA_TYPE));
    (*head)->maxSize = INIT_MAXSIZE;
    (*head)->count = 0;
}

void main(void){
    LIST *list1 = NULL;

    initList(&list1);

    destroyList(&list1);

}

2.插入操作

//在线性表下标为index的元素之前插入value 
boolean insertListElementAt(LIST *head, int index, DATA_TYPE value){
    int i;
  
    if(head->count == head->maxSize){
        printf("线性表已满,无法进行插入操作\n");
        return FALSE;
    }

     if(index < 0 || index > head->count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }

    for(i = head->count; i > index; i--){
        head->data[i] = head->data[i-1];
    }

    head->data[index] = value;

    (head->count)++;  
    //++head->count;  //课本及老师都用的这个,个人感觉在此处没有什么差异


    printf("插入成功!\n");
    return TRUE;
}
 

注意此处不可写为下面的语句:

    for(i = head->count-1; i > index; i--){
       head->data[i+1] = head->data[i];
    }

原因:若count为1,则index只能为0,此时根本无法进入循环

    

//++i     置前自增:先对变量(i)值增1,然后用增1后的值,参加所有后续运算;

//i++ 滞后自增:先用变量(i)原值参加所有的后续运算,然后再对变量值增1。

这两种插入方法的差别在于下标为index的元素是index+1个元素

//在线性表第k个元素之前插入value
boolean insertListElementAt2(LIST *head, int k, DATA_TYPE value){
    int i;


    if(head->count == head->maxSize){
        printf("线性表已满,无法进行插入操作\n");
        return FALSE;
    }


    if(k < 0 || k > head->count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }

    for(i = head->count; i > k-1; i--){
        head->data[i] = head->data[i-1];
    }

    head->data[k - 1] = value;

    //(head->count)++;  
    ++head->count;  

 
    printf("插入成功!\n");
     return TRUE;
}

//在最后一个有效元素的后面追加一个元素
boolean appendListElementAtTheLastOne(LIST *head, DATA_TYPE value){
    int count;

    if(head->count == head->maxSize){
        printf("线性表已满,无法进行插入操作\n");
        return FALSE;
    }

    head->data[head->count] = value;
    printf("追加成功!\n");
    head->count++;     //此处记得要加1
    count = countOfList(*head);
    printf("%d 分别为:", count);

    showList(*head); 
    return TRUE;

}

3.删除操作

//删除线性表中下标为index的元素
boolean deleteListElementAt(LIST *head, int index){
    int i;
 

    if(index < 0 || index > head->count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }

    for(i = index; i < head->count - 1; i++){
        head->data[i] = head->data[i+1];
    }

    head->count--;
    printf("删除成功!\n");


    return TRUE;

}

//删除线性表中第k个元素
boolean deleteListElementAt2(LIST *head, int k){
    int i;
   

    if(k < 0 || k > head->count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }

    for(i = k-1; i < head->count - 1; i++){
        head->data[i] = head->data[i+1];
    }

    head->count--;
    printf("删除成功!\n");

    return TRUE;

}

4.判定线性表为空或满

//判断线性表是否为满
boolean isListFull(LIST list){
    return list.count == list.maxSize;
}

//判断线性表是否为空
boolean isListEmpty(LIST list){
    return list.count == 0;
}


/*
boolean isListEmpty(LIST list){

    if(list.count == 0){
        return TRUE;
    }else{
        return FALSE;
    }
    return list.count == 0;
}
*/

5.查找元素

//在线性表中查找值为value的元素的下标
int getListDataBe(LIST list, int value){
    int i;

    for(i = 0; i < list.count; i++){
        if(list.data[i] == value){
            return i;
        }
    }
    return ERROR_DATA;

}

//在线性表中查找第k个元素
DATA_TYPE getListDataAt2(LIST list, int k){
    if(k < 0 || k > list.count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }

    showOneElement(list,k-1); 

    return list.data[k-1];

}

//在线性表中查找下标为index的元素
DATA_TYPE getListDataAt(LIST list, int index){
    if(index < 0 || index > list.count){
        printf("您输入的下标有误,请重新输入\n");
        return FALSE;
    }
    showOneElement(list,index); 

    return list.data[index];
}

6.输出元素

//显示线性表中的一个元素
void showOneElement(LIST list, int index){
    printf("%d ", list.data[index]);
    printf("\n");
}

//显示线性表
void showList(LIST list){
    int i;

    for(i = 0; i < list.count; i++){
        printf("%d ", list.data[i]);
    }
    printf("\n");
}

7.清空线性表

//清空线性表
void clearList(LIST *head){
    head->count = 0;
}
 


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

typedef unsigned char  boolean;
#define  TRUE    1
#define  FALSE   0

#define ERROR_DATA    -1

typedef int DATA_TYPE;                  //后续需要改动,此处只是为了测试程序
#define INIT_MAXSIZE  100

typedef struct SQ_LIST{
	DATA_TYPE *data;
	int maxSize;
	int count;
}LIST;

void initList(LIST *head);                                           //初始化顺序表
void destroyList(LIST *head);                                        //销毁线性表
boolean insertListElementAt(LIST *head, int index, DATA_TYPE value); //在线性表下标为index的元素之前插入value
boolean insertListElementAt2(LIST *head, int k, DATA_TYPE value);    //在线性表第k个元素之前插入value
boolean appendListElementAtTheLastOne(LIST *head, DATA_TYPE value);  //在最后一个有效元素的后面追加一个元素
void showList(LIST list);                                            //显示线性表
void showOneElement(LIST list, int index);                           //显示线性表中的一个元素
boolean deleteListElementAt(LIST *head, int index);                  //删除线性表中下标为index的元素
boolean deleteListElementAt2(LIST *head, int k);                     //删除线性表中第k个元素
int countOfList(LIST list);                                          //查找线性表的元素个数
boolean isListEmpty(LIST list);                                      //判断线性表是否为空
boolean isListFull(LIST list);                                       //判断线性表是否为满
DATA_TYPE getListDataAt(LIST list, int index);                       //在线性表中查找下标为index的元素
DATA_TYPE getListDataAt(LIST list, int k);                           //在线性表中查找第k个元素
int getListDataBe(LIST list, int value);                             //在线性表中查找值为value的元素的下标
void clearList(LIST *head);                                          //清空线性表



//清空线性表
void clearList(LIST *head){
	head->count = 0;
}

//在线性表中查找值为value的元素的下标
int getListDataBe(LIST list, int value){
	int i;

	for(i = 0; i < list.count; i++){
		if(list.data[i] == value){
			return i;
		}
	}
	return ERROR_DATA;

}

//在线性表中查找第k个元素
DATA_TYPE getListDataAt2(LIST list, int k){
	if(k < 0 || k > list.count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}

    showOneElement(list,k-1); 

	return list.data[k-1];

}

//在线性表中查找下标为index的元素
DATA_TYPE getListDataAt(LIST list, int index){
	if(index < 0 || index > list.count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}
    showOneElement(list,index); 

	return list.data[index];
}


//判断线性表是否为满
boolean isListFull(LIST list){
	return list.count == list.maxSize;
}

//判断线性表是否为空
boolean isListEmpty(LIST list){
	return list.count == 0;
}
/*
boolean isListEmpty(LIST list){

	if(list.count == 0){
		return TRUE;
	}else{
		return FALSE;
	}
	return list.count == 0;
}
*/

int countOfList(LIST list){
	printf("当前线性表的有效元素个数为:");
	return list.count;
}

//删除线性表中第k个元素
boolean deleteListElementAt2(LIST *head, int k){
	int i;
	int count;

	if(k < 0 || k > head->count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}

	for(i = k-1; i < head->count - 1; i++){
		head->data[i] = head->data[i+1];
	}

	head->count--;
	printf("删除成功!\n");
	count = countOfList(*head);
	printf("%d 分别为:", count);

	showList(*head); 
	return TRUE;

}
//删除线性表中下标为index的元素
boolean deleteListElementAt(LIST *head, int index){
	int i;
	int count;

	if(index < 0 || index > head->count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}

	for(i = index; i < head->count - 1; i++){
		head->data[i] = head->data[i+1];
	}

	head->count--;
	printf("删除成功!\n");

	count = countOfList(*head);
	printf("%d 分别为:", count);

	showList(*head); 
	return TRUE;

}


//显示线性表中的一个元素
void showOneElement(LIST list, int index){
	printf("%d ", list.data[index]);
	printf("\n");
}

//显示线性表
void showList(LIST list){
	int i;

	for(i = 0; i < list.count; i++){
		printf("%d ", list.data[i]);
	}
	printf("\n");
}


//在最后一个有效元素的后面追加一个元素
boolean appendListElementAtTheLastOne(LIST *head, DATA_TYPE value){
	int count;

	if(head->count == head->maxSize){
		printf("线性表已满,无法进行插入操作\n");
		return FALSE;
	}

	head->data[head->count] = value;
	printf("追加成功!\n");
	head->count++;
	count = countOfList(*head);
	printf("%d 分别为:", count);

	showList(*head); 
	return TRUE;

}

//在线性表第k个元素之前插入value
boolean insertListElementAt2(LIST *head, int k, DATA_TYPE value){
	int i;
	int count;

	if(head->count == head->maxSize){
		printf("线性表已满,无法进行插入操作\n");
		return FALSE;
	}

	//遗漏:未对下标进行判断
	if(k < 0 || k > head->count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}

//	for(i = head->count-1; i > k; i--){
//		head->data[i+1] = head->data[i];
//	}

	for(i = head->count; i > k-1; i--){
		head->data[i] = head->data[i-1];
	}

	head->data[k - 1] = value;

	//(head->count)++;  
	++head->count;  //课本及老师都用的这个,这是为什么呢???????
	//++i	 置前自增:先对变量(i)值增1,然后用增1后的值,参加所有后续运算;
    //i++ 滞后自增:先用变量(i)原值参加所有的后续运算,然后再对变量值增1。
	printf("插入成功!\n");
	count = countOfList(*head);
	printf("%d 分别为:", count);

	showList(*head); 
	return TRUE;
}

//在线性表下标为index的元素之前插入value 
boolean insertListElementAt(LIST *head, int index, DATA_TYPE value){
	int i;
	int count;


	if(head->count == head->maxSize){
		printf("线性表已满,无法进行插入操作\n");
		return FALSE;
	}

	//遗漏:未对下标进行判断
	if(index < 0 || index > head->count){
		printf("您输入的下标有误,请重新输入\n");
		return FALSE;
	}

//	for(i = head->count-1; i > index; i--){
//		head->data[i+1] = head->data[i];
//	}

	for(i = head->count; i > index; i--){
		head->data[i] = head->data[i-1];
	}

	head->data[index] = value;

	(head->count)++;  
	//++head->count;  //课本及老师都用的这个,这是为什么呢???????
	//++i	 置前自增:先对变量(i)值增1,然后用增1后的值,参加所有后续运算;
    //i++ 滞后自增:先用变量(i)原值参加所有的后续运算,然后再对变量值增1。
	printf("插入成功!\n");
	count = countOfList(*head);
	printf("%d 分别为:", count);
	showList(*head); 
	return TRUE;
}

//销毁线性表
void destroyList(LIST *head){  
	free(head->data);
}

//初始化顺序表
void initList(LIST *head){
	head->data = (DATA_TYPE *)malloc(sizeof(DATA_TYPE) * INIT_MAXSIZE);
	head->maxSize = INIT_MAXSIZE;
	head->count = 0;

	showList(*head);
}

void main(void){
	LIST list;

	boolean insertOk1;
	boolean insertOk2;
	boolean insertOk3;
	boolean insertOk4;
	boolean insertOk5;

	boolean appendOk;

	boolean deleteOk1;
	boolean deleteOk2;

	boolean empty;

	DATA_TYPE  m1;
	DATA_TYPE  m2;

	int index;

	initList(&list);

	insertOk1 = insertListElementAt(&list, 0, 10);
	insertOk2 = insertListElementAt(&list, 0, 20);
	insertOk3 = insertListElementAt(&list, 0, 30);
	
	insertOk4 = insertListElementAt2(&list, 2, 40);
	insertOk5 = insertListElementAt2(&list, 4, 50);

	appendOk = appendListElementAtTheLastOne(&list, 60);

	deleteOk1 = deleteListElementAt(&list, 1);
    deleteOk2 = deleteListElementAt2(&list, 3);

	empty = isListEmpty(list);
	printf("%d \n", empty);

	m1 = getListDataAt(list, 0);
	m2 = getListDataAt2(list, 1);


	index = getListDataBe(list, 10);
	printf("%d \n", index);

	clearList(&list);
	showList(list);

	destroyList(&list);



}

猜你喜欢

转载自blog.csdn.net/weixin_42072280/article/details/83590795