数据结构与算法实践系列文章(三)线性结构之顺序表

线性结构

什么是线性结构:

线性结构的定义

若结构是非空有限集,则有且仅有一个开始结点和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继 可表示为如下图所示。

线性结构中数据元素之间的关系就是这种“直接前驱”或“直接后继”的相邻关系,可以用一个有序对表示,如:a2与a3的关系:<a2,a3>

在这里插入图片描述

线性结构的特点:

只有一个首结点和尾结点;

② 除首尾结点外,其他结点只有一个直接前驱和一个直接后继。

线性结构包括线性表、堆栈、队列、字符串、数组等等,其中,最典型、最常用的是线性表

线性表:

是一种最简单的线性结构。简单地说,是一个有序集合:用数据元素的有限序列表示

是由n个数据元素(结点) 常常将非空的线性表记为L = (a1,a2,a3,a4,a5… an);

其中

  • L:是线性表的表名
  • n表示数据元素的个数,当n=0时成为空表。表中的数据元素a时一个抽象的符号,成为i在ai在线性表中的位序。

DizsV1.png

线性表四个基本特征:

1.集合中必存在唯一的一个“第一元素”;

2.集合中必存在唯一的一个“最后元素”;

3.除最后元素之外,其它数据元素均有唯一的“直接后继”;

4.除第一元素之外,其它数据元素均有唯一的“直接前驱”;

线性表的顺序表示又称为顺序存储结构或顺序映像

线性表的存储

用一组地址连续的存储单元依次存放线性表中的数据元素。借助元素在存储器中的相对位置来表示 数据元素间的逻辑关系

顺序表
定义:

顺序表是线性表的顺序存储表示的简称,它指的是,“用一组地址连续的存储单元依次存放线性表中的数据元素”,即以“存储位置相邻”表示“位序相继的两个数据元素之间的前驱和后继的关系

(有序对<ai-1,ai)”,并以表中第一个元素的存储位置作为线性表的起始地址,称作线性表的基地址

顺序存储定义: 把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构

顺序存储方法: 用一组地址连续的存储单元依次存储线性表的元素,可通过数组V[n]来实现

顺序表的类型定义:

#define  MAXSIZE 100     //最大长度
typedef  struct {
  ElemType  *elem;     //指向数据元素的基地址
  int  length;          //线性表的当前长度                                                      
 }SqList;

顺序表存储结构定义:

#define MAXSIZE 10000	//图书表可能达到的最大长度 
typedef struct			//图书信息定义
{ 
   char no[20];			//图书ISBN
   char name[50];		//图书名字
   float price; 			//图书价格
}Book; 
typedef struct
{ 
   Book *elem;	//存储空间的基地址 
   int length;		//图书表中当前图书个数 
}SqList;		//图书表的顺序存储结构类型为SqList

顺序表的特点:

(1)利用数据元素的存储位置表示线性表中相邻数据元素之间的前后关系,即线性表的逻辑结构与存储结构一致

( 2 )在访问线性表时,可以快速地计算出任何一个数据元素的存储地址。因此可以粗略地认为, 访问每个元素所花时间相等

顺序表的优缺点:

优 点:

  1. 存储密度大 (结点本身所占存储量 / 结点结构所占存储量)
  2. 可以 随机存取 表中任一元素

缺点:

  1. 在插入、删除某一元素时,需要移动大量元素
  2. 浪费存储空间
  3. 属于静态存储形式,数据元素的个数不能自由扩充

c语言动态分配函数:

malloc(m):开辟m字节长度的地址空间,并返回这段空间的首地址

sizeof(x):计算变量x的长度

free§:释放指针p所指变量的存储空间,即彻底删除一个变量

实现线性表
C语言

DiHTUg.png

代码:

#include <stdio.h>

#define MAX 10

// 使用结构体
struct Slist{
    int data[MAX];
    int length;
};
// 初始化
void init(struct Slist* p){
    p->length =0;
}
// 打印
void printList(const struct Slist* p){
    for(int i=0;i<p->length;i++){
        printf("%d",p->data[i]);
    }
    putchar('\n');
    
}
// 插入
int insert(struct Slist* p, int k, int x){
    // 判断插入的位置
    if(k<0 || k> p->length || p->length==MAX-1) return 0; // 表示失败
    for(int i=p->length-1;i>=k;i++){
        // 元素向后挪一位
        p->data[i+1] = p->data[i];
    }
    p->data[k] = x;
    p->length++;
    return 1;
    
}

// 删除
int delete1(struct Slist* p, int k, int *px){
    if(k<0 || k >= p->length) return 0;
    else {
        *px = p->data[k];
        for(int i= k+1; i<p->length;i++){
            p->data[i-1] = p->data[i];
        }
        p->length--;
        return 1;
    }
}
int main(void) { 
    struct Slist a;
    init(&a);
    // 插入 在0号元素插入x
    int k=0,x=11;
    insert(&a,k, x);
    
    // 删除并将返回删除的值的地址。
    int addr;
    delete1(&a, 1,&addr);
    // 这里传入a的话就会copy一份数组了,所以这里使用地址进行传入
    printList(&a);
	return 0;
}
c++
#include <iostream>
#include <list>
#include <vector>
#include <stack>
using namespace std;
int main(int argc ,const char * argv[]) {
   vector<int> v;
   v.push_back(11);
   v.push_back(12);
   v.push_back(13);
   // 使用迭代器
   vector<int> ::iterator it;
   for(it=v.begin(); it!=v.end();it++){
       cout<< *it << ",";
   }
   cout << endl;
    // 插入
   v.insert(v.begin(),666); // 在 0 号位置进插入
   v.insert(v.begin()+2, 333); // 在 2号位置进行插入
    // 删除
   v.erase(v.begin()+1); // 
   for(int i:v){
       cout << i << ",";
   }
    
   cout << endl;
	return 0;
}
java
public void testArrayList(){
    ArrayList<Integer> list = new ArrayList<>();
   	list.add(123);
    list.add(234);
    // 在1号位置插入
    list.add(1,666);
    // 移除某个下标的。返回删除的元素
    int k=list.remove(2);
    
}
// 实现自己的顺序表
package com.java1995;

public class ArrayList {
	//定义Object[]数组;
	private Object[] objs;
	
	public 	ArrayList(){
		//初始容量
		objs=new Object[10];
	}
	public ArrayList(int size){
		objs=new Object[size];
	}
	//增加的方法
	public boolean add(Object obj){
		int index=-1;
		for(int i=0;i<objs.length;i++){
			if(objs[i]==null){//未放数据;
				index=i;
				break;
			}
		}
		if(index==-1){//要扩容;
			int oldlen=objs.length;
			//创建新的数组;
			Object[] objs2=new Object[objs.length*2];
//			老数组的数据复制到新的数组中;
			System.arraycopy(obj, 0, objs2, 0, objs.length);
			objs=objs2;
			objs[oldlen]=obj;
		}else{
			objs[index]=obj;
		}
		return true;
	}
	//删除的方法;
	public Object remove(int index){
		Object obj=objs[index];
		objs[index]=null;
		return obj;
	}
	//修改的方法;
	public Object set(int index,Object newobj){
		Object oldobj=objs[index];
		objs[index]=newobj;
		return oldobj;
		
	}
	//查找的方法;
	public Object get(int index){
		return objs[index];
	}
	@Override
	public String toString() {
		StringBuffer sb=new StringBuffer();
		//sb.append("[");
		for(Object obj: objs){
			if(obj==null)continue;
			sb.append(obj+" ");
		}
		//sb.append("]");
		return sb.toString();
	}
	
}

Python
a=list();
a.append(11);
a.append(222);
# 插入
a.insert(3,33);
# 删除 用栈的方式弹出
a.pop(1);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值