数据结构-线性表(顺序表+链表)

线性表

1、线性表是一种逻辑结构,表示一种一对一的逻辑关系,除首节点和尾节点,每个结点只有一个前驱结点和一个后继结点
2、两种实现的物理结构:顺序存储,链式存储

顺序表

1、定义:用一组地址连续的存储单元,一次存储线性表中的元素,使得逻辑位置相邻的元素物理位置也相邻。
2、特点:
顺序表元素的位序从1开始
顺序表可以随机访问,通过首地址和序列号找到指定元素的时间复杂度为O(1)
顺序表存储密度高,每个结点只存储数据元素
顺序表进行插入删除操作平均时间复杂度为O(n)
顺序表的一维数组可以静态分配也可以动态分配。

(一)静态分配

#include <iostream>
#include<stdlib.h>
#include<time.h>

#define SIZE 100
#define OK 1
#define ERROR 0

//静态存储
typedef struct {
    int data[SIZE];
    int length;
}SqlList; 

//初始化表,构造一个空的线性表
int initList(SqlList &L){
    L.length = 0;
    return OK;
} 
//求表长 
int Length(SqlList L,int &len){
    if(L.data == NULL){
        return ERROR;   
    } 
    len = L.length;
    return OK;
} 
//利用随机数创建顺序表 
int creatList(SqlList &L,int len){
    if(L.data==NULL|| len<=0) return ERROR;
    //srand(time(NULL));
    for(int i = 0;i<len;i++){
        L.data[i] = rand()%100+1;
    }
    L.length = len;
    return OK;
}
//打印链表
int printList(SqlList L){
    if(L.data==NULL) return ERROR;
    for(int i = 0;i<L.length;i++){
        printf("%4d",L.data[i]);
    }
    printf("\n");
    return OK;
} 
//在链表第i个元素插入元素 
int insertList(SqlList &L,int i,int e){
    if(L.data == NULL)
    return ERROR;
    if(i<1 || i>L.length+1)//插入位置不合法 
    return ERROR;
    if(L.length>=SIZE)//存储空间已满 
    return ERROR; 

    for(int j = L.length;j>=i;j--){
        L.data[j] = L.data[j-1];
    }
    L.data[i-1] = e;
    L.length++;
    return OK;
} 
//删除链表第i个位置的元素,并返回元素的值 
int deleteList(SqlList &L,int i,int &e){
    if(L.data == NULL)
    return ERROR;
    if(i<1 || i>L.length+1)//删除位置不合法 
    return ERROR;
    e = L.data[i-1];
    for(int j=i;j<L.length;j++){
        L.data[j-1] = L.data[j];
    } 
    L.length--;
    return OK;

} 
//按位查找,获取表第i个位置的元素值
int getElem(SqlList L,int i,int &e){
    if(L.data==NULL)
    return ERROR;
    if(i<1||i>L.length)
    return ERROR;
    e = L.data[i-1];
    return OK;
} 
//按值查找,在表中查找具有给定关键值的元素,只返回第一个匹配元素的位置 
int LocateElem(SqlList L,int e,int &locate){
    if(L.data==NULL)
    return ERROR;
    for(int i = 0;i<L.length;i++) {
        if (L.data[i] == e) {
            locate = i+1;
            return OK;
        }
    }
    locate = NULL;
    return OK;
} 
//判断线性表是否为空
bool isEmpty(SqlList L){
    if(L.length == 0) 
    return true;
    else
    return false;
} 
int main(){
//顺序表一般都是由数组实现的,并不是动态内存。
//根据进程空间的概念到函数退出或者程序结束的时候会自动释放。
//所以不用单独释放内存,增加开销
    SqlList L;
    initList(L);
    int e = 0 ;
    //创建表 
    creatList(L,10);
    printList(L);
    //插入表 
    insertList(L,3,1);
    printList(L);
    //删除表 
    deleteList(L,3,e);
    printList(L);
    printf("%d\n",e);
    //按位查找
    getElem(L,3,e);
    printf("%d\n",e);
    //按值查找
    LocateElem(L,1,e);
    printf("%d\n",e);
    return 0;
} 

这里写图片描述
(二)动态分配
参考博客:
http://blog.csdn.net/doudouwa1234/article/details/45840805
关于ifndef的用法
http://blog.csdn.net/mozha_666/article/details/79485105


链表

1、逻辑位置相邻,物理位置不一定相邻的线性表。
2、适合做插入删除操作
3、分类:单链表,双链表,区分依据是含有几个指针域

(一)单链表

#include<stdio.h> 
#include<stdlib.h>
typedef int ELemType ;

typedef struct LNode{
    ELemType data;
    struct LNode *next;
}LNode,*LinkList;

//头插法创建单链表 
LinkList createLinkListByHead(LinkList &L){
    LNode *s;
    int x;  
    //创建头结点
    L = (LinkList)malloc(sizeof(LNode));
    //初始化单链表 
    L->next = NULL;
    scanf("%d",&x);
    while(x!=9999){
        //开辟新结点
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;
        L->next = s; 
        scanf("%d",&x);
    }
    return L;
} 

//尾插法创建单链表
LinkList createLinkListByTail(LinkList &L){
    LNode *s,*r;
    int x;
    //创建头结点
    L = (LinkList)malloc(sizeof(LNode));
    //初始化链表
    L->next = NULL;
    r = L;//设置一个尾指针 
    while(scanf("%d",&x) && x!=9999){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;//r指向新的表尾结点 
    } 
    r->next = NULL;
    return L;
}
//打印单链表
void printLinkList(LinkList L){
    if(L->next == NULL){
        printf("单链表为空\n");
        return ; 
    }
    LNode *s  = L;
    while(s->next!=NULL){
        s = s->next;
        printf("%4d",s->data); 
    }
    printf("\n");
} 
//按位查找 查找第i个位置的元素值 
LNode * getElem(LinkList L,int pos){
    if(pos<=0) return NULL;
    int i = 1;
    LNode *s = L->next;
    while(s&&(i<pos)){
        s = s->next;
        i++;
    }
    return s;
}
//按值查找结点 和该节点的位置 
int locateElem(LinkList L,int e){
    if(L->next == NULL){
        printf("链表为空,元素值不存在\n");
        return 0; 
    }
    LNode *s  = L->next;
    int pos = 1;
    while(s){
        if(s->data == e) return pos;
        s = s->next;
        pos++;
    }
    pos = 0;
    return pos;
} 
int main(void){

    LinkList L;
    //头插法 
//  printf("请输入数值\n");
//  createLinkListByHead(L);
//  printLinkList(L);
    //尾插法 
    printf("请输入数值\n");
    createLinkListByTail(L);
    printLinkList(L);
    int pos  = 0;
    LNode *s = getElem(L,pos);
    if(s){
        printf("第%d个元素值是%d\n",pos,s->data);
    }
    else{
        printf("第%d个元素值不存在\n",pos);
    }
    pos = locateElem(L,5);
    if(pos){
        printf("位置%d\n",pos);   
    }
    else{
        printf("不存在\n",pos);    bgh
    } 

    return 0;
}

(二)双链表

这里写代码片

(三)循环单链表

这里写代码片

(四)循环双链表

这里写代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值