线性结构-数组和链表的实现

Posted zklgy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性结构-数组和链表的实现相关的知识,希望对你有一定的参考价值。

 
 
 
 连续存储(数组)
                     1、什么叫数组?
                           元素的类型相同,大小相等。
                     2、优缺点?
                           查询速度快,增加删除慢
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//定义一个数据类型,名字 Arr,成员分别
struct Arr
{
    int * pBase;      //存储的是数组第一个元素的地址
    int len;          //数组的长度
    int cnt;          //当前数组有效元素的个数
    int increment;    //自动增长因子,扩容
};
//参数一定要传地址,如果是变量只是把12个字节赋给了另12个字节,进行初始化
void init_arr(struct Arr * pArr , int length)
{
    pArr->pBase = (int *)malloc(sizeof(int)*length)//相当于指针变量中结构体变量pBase成员,返回二十四个字节的第一个字节
        if(NULL == pArr->pBase) //检测是否分配成功
        {
            printf("动态内存分配失败!\\n");
            exit(-1); //终止整个程序
        }
        else
        {
            pArr->len = length;
            pArr->cnt = 0;
        }
};
//添加到数组尾部
bool append_arr(struct Arr * pArr , int val)
{
    //满时直接返回
    if(is_full(pArr))
        return false;
    //不满追加
    else
        pArr->pBase[pArr->cnt] = val ;
        pArr->cnt++
};
//插入指定位置,下标为0的是第一个元素
bool insert_arr(struct Arr * pArr,int pos,int val)
{
    int i ;
    if(is_full(pArr)) return false;
    if(pos<1||pos>pArr->cnt+1) return false;
    for(i = pArr->cnt - 1; i>=pos-1; --1)
    {
        pArr->pBase[i+1] = pArr->pBase[i];// 数组下标灯油POS的元素向后移
    }
    pArr->pBase[pos-1] = val;    //赋值POS位置
    pArr->cnt++;
    return true;
};
bool get();
//是否为空
bool is_empty(struct Arr * pArr)
{
    if(0== pArr->cnt)
    {
        return true;
    }
    else
    {
        return false;
    }
};
bool delete_arr(struct Arr * pArr,int pos,int val)
{
    int i;
    if(is_empty(pArr))
    {
        return false;
    }
    if(pos<1 || pos>pArr->cnt)
    {
        return false;
    }
    *val = pArr->pBase[pos-1]; //返回删除的元素
    for(i=pos;i<pArr->cnt ; ++i)
    {
        pArr->pBase[i-1] = pArr->pBase[i];
    }
    pArr->cnt--;
    return true ;
};
//是否满了
bool is_full(struct Arr * pArr)
{
    if(pArr->cnt == pArr->len)
        return true;
    else
        return false;
};
void sort_arr(struct Arr * pArr)
{
    int i,j,t;
    for(i=0;i<pArr->cnt;++i)
    {
        for(j=i+1; j<pArr->cnt ;++j)
        {
            if(pArr->pBase[i] > pArr->pBase[j])
            {
               t=pArr->pBase[i];
               pArr->pBase[i]= pArr->pBase[j];
               pArr->pBase[j]=t;
            };
        }
    }
    
};
//最好传地址,不需要重新分配内存,输出
void show_arr(struct Arr * pArr)
{
    if(is_empty(pArr))
    {
     printf("数组为空!\\n");
    }
    else
    {
     for(int i = 0; i<pArr->len;++i)
     {
     printf("%d",pArr->pBase[i]);
     }
    }
};
//倒置
void inversion_arr(struct Arr * pArr)
{
    int i =0;
    int j=pArr->cnt-1;
    int t;
    while(i<j)
    {
        t=pArr->pBase[i];
        pArr->pBase[i]=pArr->pBase[j];
        pArr->pBase[j]=t;
        ++i;
        --j;
    }
};

int main(void)
    {
    struct Arr arr; //定义一个数据类型,此时的地址全是垃圾地址
    int val ; //删除时,用来返回删除的元素
    init_arr(&arr,6);
    show_arr(&arr);
    append_arr(&arr , 1);
    insert_arr(&arr , 1,10);
    delete_arr(&arr , 1,&val);
    inversion_arr(&pArr);
    sort_arr(&pArr);
        return 0;
    }
离散存储(链表)
                定义:
                         N个结点离散分配,彼此通过指针相连,分配结点只有一个前驱结点和后续结点,首节点没有前驱结点,尾结点没有后续结点,
                        首节点:第一个有效结点
                        尾节点:最后一个有效结点
                        头节点:第一个有效结点前的节点,头节点不存放数据,但是数据类型跟后面节点的数据类型相同
                        头指针:指向头节点的指针变量
                        尾指针:指向尾节点的指针变量
技术分享图片

 

分类:
                        单链表,
                        双链表:每个节点有两个指针
                        循环链表:可以通过任何一个节点找到所有结点
                        非循环链表
                算法:
                        插入时分析
技术分享图片

        删除时分析

技术分享图片

需要定义一个中间值
 
                优缺点:        
 
                一个节点的生成:
技术分享图片

 

#include <stdio.h>
#include <malloc.h>
//定义节点
typedef struct Node
{
    int data;//数据域
    struct Node *pNext; //指针域
} NODE,*PNODE; //NODE等价于struct NODE ,PNODE等价于struct NODE *

int main(void)
    {
    PNODE pHead = NULL; //等价struct NODE * pHead = null; (定义一个头节点)
    pHead = create_list(); //创建一个非循环单链表并将该链表的第一个单元返回
    traverse_list(pHead);
        return 0;
    }
PNODE create_list(void)
{
    int len = 5;
    int i;
    int val;
    PNODE pHead =(PNODE)malloc(sizeof(NODE)); //NODE结构体值类型,PNODE结构体地址类型
    if(NULL == pHead)
    {
        exit(-1);
    }
    PNODE pTail = pHead; //定义一个尾节点
    pTail->pNext =NULL;  //清空指针域(保证尾节点始终指向最后一个)
    for(i=0 ; i<len ; i++)
    {
       PNODE pNew = (PNODE)malloc(sizeof(NODE));//存放每个节点的临时值   
        if(NULL == pNew)
        {
            exit(-1);
        }
        pNew ->data = val; //数据域赋值
        pTail->pNext = pNew; //指向下一个节点
        pNew->pNext = null;  //清空下一个节点的指针域
        pTail=pNew;          //下一个节点赋值给尾节点 (保证pTail 永远指向尾节点这是关键)
    }
    return pHead;
}

//输出
void traverse_list(PNODE pHead)
{
    PNODE p = pHead->pNext; //指向第一个有效节点
    while(NULL !=p)
    {
        printf("输出数据域");
        p=p->pNext;
    }
    return;
}
//是否为空
bool is_empty(PNODE pHead)
{
    if(NULL==pHead->pNext) return true;
    return false;
};
//输出长度
int length_list(PNODE pHead)
{
    int i = 0;
    PNODE p=pHead->pNext;
    while(NULL!=p)
    {
        i++;
        p=pHead->pNext;
    }
    return i;
};
//插入节点(在pHead所指向链表的Pos个节点前面插入个新节点,该值是val)
bool insert_list(PNODE pHead , int pos, int val)
{
    int i=0 ;
    PNODE p =pHead
    while (NULL!=p &&i >pos-1)
    {
        p = p->pNext;
        ++i;
    }
     if(i>pos-1 || NULL == p)//判断最后一个节点的位置以及长度和最后一个节点是否为NULL
     {
         return false;
     }
    PNODE pNew =(PNODE)malloc(sizeof(NODE));
    if(NULL == pNew)
    {
        printf("动态分配内存失败");
    }
    pNew ->data =val;
    PNODE  q=p->pNext; 
    p->pNext= pNew;
    pNew->pNext =q;
};
//删除一个元素
bool delete_list(PNODE pHead , int pos, int * val)//val是返回删除的元素
{
    int i=0 ;
    PNODE p =pHead
    while (NULL!=p->pNext &&i >pos-1) //找到要删除节点的前一个节点
    {
        p = p->pNext;
        ++i;
    }
     if(i>pos-1 || NULL == p->pNext)//判断最后一个节点的位置以及长度和最后一个节点是否为NULL
     {
         return false;
     }
    PNODE q=p->pNext;
    *pVal = q ->data;
    
    //删除
    p->pNext = p->pNext->pNext;
    free(q);
    q=NULL;
        
    
};

//排序(链表的排序跟数组的排序不同,但是逻辑相同)
bool sort_list(PNODE pHead)
{
    int i,j,t;
    int len=length_list(pHead);
    PNODE p,q;
    for(i=0,p=pHead->pNext;i=len-1;++i , p=p->pNext)
    {
        for(j=i+1,q=p->pNext;i=len-1;++j,q=q->pNext) //循环的同时移动指针q的位置
        {
            if(p->data > q->data) //类似a[i]>a[j]
            {
                t=p->data;//换值
                p->data = q->data;
                q->data=t;
            }
        }
    }
};

 

 


以上是关于线性结构-数组和链表的实现的主要内容,如果未能解决你的问题,请参考以下文章

C中线性表和链表的区别

数据结构之顺序表(数组)和链表

线性表——顺序表和链表

Java用数组和链表实现队列

浅谈数组和链表

链表是顺序表吗?