【Data structure】Linear table|C/C++ realizes dynamic and static allocation and basic operations of sequence table|2021 Wang Dao data structure notes arrangement

The physical/storage structure of the linear table-sequence table

[Written in the front] This blog is the author's notes organized according to the video course of the 2021 Wangdao Data Structure PubMed Review Guide. All of them have been tested and feasible with a compiler. Some functions have been improved in code robustness according to the teacher's prompts, so you can use them with confidence.

1. Relevant knowledge of the sequence table

1.1. The concept of sequential storage

sequential storage: It refers to storing logically adjacent elements in physically adjacent storage units, and the relationship between elements is reflected by the adjacency relationship of storage units.

1.2. How to know the size of a data element

in C language assizeof(ElemType)
ElemType is the data element type stored in your sequence table.
eg:

sizeof(int)=4B;   
sizeof(Customer)=8B;//Customer为包含两个整型元素的结构体                                                                                                  

Second, the implementation of the sequence table: static allocation

2.1, static allocation

 使用数组的方式来存放顺序表,数组的长度大小一旦确定了之后就不可以改变,这是静态数组的特点。
 分配一整片连续的存储空间,大小为MaxSize*sizeof(ElemType)。
#define Maxsize 10           //宏定义一个常量,定义最大长度
typedef struct{
    
    
    ElemType data[MaxSize];  //定义了一个静态数组,大小为Maxsize,用来存放数据元素
    int length;              //顺序表的当前长度
}SqList;                     //Sq表示sequence(顺序、序列)
//自己写代码的时候ElemType是什么类型吧ElemType替换掉就可以了。

2.2. Statically allocate a sequence table for storing integer data, initialize the sequence table, and output

#include<stdio.h>
#define Maxsize 10 //定义最大长度
typedef struct {
    
    
	int data[Maxsize];  //定义一个长度为Maxsize的数组用来存放数据元素
	int length;         //顺序表的当前长度
}SqList;  

//基本操作——初始化一个顺序表
void InitList(SqList &L) {
    
    
	for (int i = 0;i < Maxsize;i++) {
    
    
		L.data[i] = 0;  //将所有数据元素设置为默认初始值0
	}
	L.length = 0;
}

void PrintList(SqList L) {
    
    
	for (int i = 0;i < Maxsize;i++) {
    
    
		printf("%d  ",L.data[i]);
	}
	printf("\n%d  ", L.length);
}

int main() {
    
    
	SqList L;    //声明一个顺序表
	InitList(L);  //初始化顺序表
	PrintList(L);
	return 0;
}

Printout content:
insert image description here

2.3. [Note] If the initial value is not assigned to data[i], the dirty data left in the memory will be output.

The test is as follows. Change the initialization function in the previous code to the following, compile and test, and the output is as follows.

//基本操作——初始化一个顺序表
void InitList(SqList &L) {
    
    
	//for (int i = 0;i < Maxsize;i++) {
    
    
	//	L.data[i] = 0;  //将所有数据元素设置为默认初始值0
	//}
	L.length = 0;
}

Print output content:
insert image description here
[Note] In fact, the above method of accessing the array with i<Maxsize is illegal, but should be accessed with i<length, because you should not access from the first element to the last element but should access the last element of the actual length currently stored.

2.4, other notes

1. 给各个数据元素设置默认值的步骤可以省略,因为按正常的访问方式的话,
   其实不应该访问超过顺序表实际长度的数据元素。
   这种访问方式也不够好,更好的做法是使用基本操作来访问各个数据元素。
3. Q:C语言不是会自动给int型的变量设置初始值为0吗?
   A:设置初始值是编译器做的事情,换一个C语言的编译器可能不会帮你做初始化的工作。
      所以当我们声明一个顺序表的时候,把它的length值设置为0这一步是必须做的。
4. Q:如果数组存满了怎么办?
   A:直接放弃治疗,顺序表的表长一旦确定了就无法更改。(存储空间是静态的)
5. Q:如果刚开始就声明一块很大的存储空间,存在什么问题?
   A:很浪费。

3. Implementation of sequence table: dynamic allocation

3.1, dynamic allocation

The sequence table to define a dynamic allocation with code is as follows:

#define InitSize 10     //定义顺序表的初始长度
typedef struct {
    
        
ElemType *data;     //指示动态分配数组的指针      
int MaxSize;        //顺序表的最大容量    
int length;         //顺序表的当前长度
 }SeqList;         //顺序表的定义类型(动态分配方式) 

3.2. The key to dynamic allocation: dynamic application and release of memory space - the use of malloc and free functions

C language provides malloc and free functions to dynamically apply and release memory space.The two functions malloc and free are contained instdlib.hin this header file. In C++, the new and delete keywords are used to realize the above functions.

2.1 malloc function

L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);

Format: L.data=(ElemType*) malloc(sizeof(ElemType)*InitSize);

Function: Allocate a whole piece of contiguous memory space. Then return a pointer to the starting address of this piece of storage space. Needs to be cast to a pointer to the data element type you define. data is a pointer to the starting address of this storage space.

The parameters of the malloc function: specify how much continuous memory space to allocate. For example, the above is to allocate the memory space of InitSize elements whose size is sizeof(ElemType).

3.3. Expand the memory space of the dynamic allocation sequence table

Dynamically allocate a sequence table for storing integer data, initialize the sequence table, expand the memory space of the sequence table by 5, and output

#include<stdio.h>
#include<stdlib.h>
#define InitSize 10 //定义最大长度
typedef struct {
    
    
	int *data;          //指示动态分配数组的指针  
	int MaxSize;        //顺序表的最大容量
	int length;         //顺序表的当前长度
}SeqList;               //顺序表的定义类型(动态分配方式)  

//基本操作——初始化一个顺序表
void InitList(SeqList &L) {
    
    
	//用malloc函数申请一片连续的存储空间
	L.data = (int *)malloc(sizeof(int)*InitSize);
	L.length = 0;
	L.MaxSize = InitSize;
}

//增加动态数组的长度
void IncreaseSize(SeqList &L,int len) {
    
    
	int *p = L.data;
	L.data = (int *)malloc(sizeof(int)*(L.MaxSize+len));//新申请一篇长度为Maxsize+len的区域
	for (int i = 0;i < L.length;i++) {
    
    
		L.data[i] = p[i];//将数据复制到新区域
	}
	L.MaxSize = L.MaxSize + len;
	free(p); //free(p)用来释放p指向的内存空间,由于p是在函数内的局部指针变量,在函数执行完后,存放指针p的内存空间也会被自动释放。
}


void PrintList(SeqList L) {
    
    
	for (int i = 0;i < L.MaxSize;i++) {
    
    
		printf("%d  ",L.data[i]);
	}
	printf("\n%d  ", L.length);
}

int main() {
    
    
	SeqList L;    //声明一个顺序表
	InitList(L);  //初始化顺序表
	IncreaseSize(L,5);
	PrintList(L);
	return 0;
}

The printout content compiled in VS:
insert image description here
memory creation process:
insert image description here

Fourth, the characteristics of the sequence table

  1. Random access: The i-th element can be found in O(1) time (the code is implemented as data[i-1], static allocation and dynamic allocation are the same).
  2. High storage density: each node only stores data elements (while chained storage also stores pointers to the next data element).
  3. It is inconvenient to expand the capacity (the static allocation method cannot expand the capacity, even if the dynamic allocation method is used, the time complexity of expanding the length is relatively high).
  4. Insertion and deletion operations are inconvenient, and a large number of elements need to be moved.

Five, the basic operation of the sequence table

5.1, insert operation (static allocation)

//基本操作:插入元素
void ListInsert(SqList &L, int i, int e) {
    
    
	for (int j = L.length;j >= i;j--) {
    
    
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
}

To increase the robustness of the code, after modification:

//基本操作:插入元素
bool ListInsert(SqList &L, int i, int e) {
    
    
	if(i<1|| i>L.length+1){
    
      //判断i的范围是否有效,无效返回false
		return false;
	}
	if (L.length >= Maxsize) {
    
       //当前存储空间已满,不能插入
		return false;
	}
	for (int j = L.length;j >= i;j--) {
    
    
		L.data[j] = L.data[j - 1];
	}
	L.data[i - 1] = e;
	L.length++;
	return true;
}

Time complexity analysis: deepest loop L.data[j] = L.data[j - 1];
best O(1), worst O(n), average O(n).

5.2. Delete operation

//基本操作:删除位序为i的元素
bool ListDelete(SqList &L, int i, int &e) {
    
    
	if (i<1 || i>L.length) {
    
    
		return false;
	}
	e = L.data[i - 1];
	for (int j = i;j < L.length;j++) {
    
    
		L.data[j - 1] = L.data[j];
	}
	L.length--;
	return true;
}

Time complexity analysis:
best O(1), worst O(n), average O(n).

5.3. Bitwise search: time complexity O(1)

//基本操作:按位查找
int GetElem(SqList L,int i) {
    
    
	return L.data[i - 1];//动态和静态都是用这一条查找
}

5.4. Search by value: best time complexity O(1), worst O(n), average O(n)

int LocateElem(SeqList L, int e) {
    
    
	for (int i = 0;i < L.length;i++) {
    
    
		if (L.data[i] == e)   //基本数据类型如bool、double等都可以直接用==来比较但是结构体不可以,结构体需要写专门的判断语句来逐一判断其中的元素是否相等
			return i + 1;
	}
	return 0;
}

6. Test code

Due to space reasons, the author puts the test code in another blog post, and the link is [Data Structure (2)] Linear Table | Sequence Table | (Full) Test Code | Use C language/C++ to implement basic operations such as definition, insertion, deletion, search, and printout of dynamic and static sequence tables . All have been tested and run in the VS compiler, including tests for all the above basic operations.

Guess you like

Origin blog.csdn.net/dxy1128/article/details/107951674