数据结构 第二章线性表 第二节

89 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

数据结构

第二章

二、顺序表

线性表的顺序存储结构。将线性表的所有元素按照逻辑顺序依次存储到计算机指定位置的一块连续空间中了。由于在逻辑结构上相邻的线性表元素,存储位置上也相邻,所以这种映射也叫直接映射

image.png

顺序表的实现

采用静态分配实现顺序表

使用"静态"的数组存储元素(初始化时,数组长度被固定)。

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 5 //定义一个常数
void create(); 
typedef struct Node{
	int data[MaxSize];//初始化data长度
	int length;
}Node;
int main(){
	create();
	return 0;
} 

void create(){
	int i;
	Node node;
	node.length=MaxSize;
	for(i=0;i<node.length;i++){
		node.data[i]=i;//给结构体的data数组赋值
		printf("value:%d\n",node.data[i]);
	}
	
}

采用动态分配实现顺序表

动态分配空间。

#include <stdio.h>
#include <stdlib.h>
//#define MaxSize 5
void create(int value); 
typedef struct Node{
	int *data;//定义一个指针,用于申请动态长度。 
	int length;
}Node;
int main(){
	create(5);
	return 0;
} 

void create(int value){
	int i;
	Node node;
	node.length=value;
	node.data=(int *)malloc(sizeof(int)*value);//申请一段连续的空间地址 
	for(i=0;i<node.length;i++){
		node.data[i]=i;
		printf("value:%d\n",node.data[i]);
	}
	
}

顺序表的特点

  • 随机访问,可以在O(1)时间内找到第i个元素。(随机访问:可以随意访问该数据结构中的任意一个节点,如果是链表,那么每次都需要从头或尾依次遍历,时间复杂度高)
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
	int *data;//定义一个指针,用于申请动态长度。 
	int length;
}Node;
//#define MaxSize 5
Node create(int value); 
int getItem(Node node,int item);

int main(){
	Node node;
	node=create(5);
	int value=getItem(node,2);
	printf("value:%d",value);
	return 0;
} 

Node create(int value){
	int i;
	Node node;
	node.length=value;
	node.data=(int *)malloc(sizeof(int)*value);//申请一段连续的空间地址 
	for(i=0;i<node.length;i++){
		node.data[i]=i;
//		printf("value:%d\n",node.data[i]);
	}
	return node;
	
}
//获取第i个元素的时间复杂度为O(1)
int getItem(Node node,int item){
	return node.data[item];
}
  • 存储密度高,每个节点只存储数据元素。
  • 扩展容量不方便,即使使用动态分配的方式,扩展长度的时间复杂度也会比较高。
  • 插入、删除操作不方便,需要移动大量元素。 image.png

总结

image.png

顺序表的基本操作——插入和删除

插入

bool insertValue(Node node,int i,int value){
	int j,item;
	node.length=node.length+1;
	if(i>node.length||i<1){
		return false;
	}else{
		for(j=node.length-1;j>i;j--){
			node.data[j+1]=node.data[j];
		}
		node.data[i]=value;
		printf("输出:%d,%d,%d",node.data[i],node.length,value); 
		return true;
	}
}

当前插入操作的时间复杂度为O(n);
最坏时间复杂度:要插入的元素是数组的第一个位置,那么时间复杂度为O(n);
最好时间复杂度:要插入的元素是数组的最后一个位置,那么时间复杂度为O(1);
平均时间复杂度:要插入的元素在数组的任何一个位置插入元素的位置的时间复杂度就为 np+(n-1)p+...+1*p=O(n);(此处第一个为n,是因为插入元素的位置可能是在最后一个,数组的长度会在此原数组基础上增加一个)

删除

bool deleteValue(Node node,int i){
	int j;
	if(i>node.length||i<0){
		return false;
	}else{
		for(j=i;j<node.length;j++){
			node.data[i]=node.data[i+1];
		}
		node.length=node.length-1;
		printf("当前值为:%d\n",node.data[i]);
		return true;
	}

}

当前插入操作的时间复杂度为O(n);
最坏时间复杂度:要插入的元素是数组的第一个位置,那么时间复杂度为O(n);
最好时间复杂度:要插入的元素是数组的最后一个位置,那么时间复杂度为O(1);
平均时间复杂度:要插入的元素在数组的任何一个位置删除元素的时间复杂度就为 (n-1)p+(n-2)p+...+1*p=O(n)(此处n-1的位置代表是数组的最后一个元素的位置)

顺序表的基本操作——按位查找和按值查找

按位查找

按照位序查找元素

int getItem(Node node,int item){
	return node.data[item];
}

以上算法的时间复杂度为O(1);

按值查找

按照值查找元素位置

int getValue(Node node,int value){
	int i=0;
	while(node.data[i]!=value){
		i++;
	}
	printf("值为:%d",i);
	return i;
}

以上算法的时间复杂度为O(n); 最好时间复杂度:要查找的元素位置在第一个,那么时间复杂度为O(1); 最坏时间复杂度:要查找的元素位置在最后一个,那么时间复杂度为O(n); 平均时间复杂度:要查找的元素位置在任意一个位置的概率为p=1/n,时间复杂度为 (n-1)p+(n-2)p+...+1*p=O(n)

总结

image.png