数据结构(顺序表,单链表,双链表,堆栈,队列,二叉树)

day1

顺序表:

1.逻辑结构:按顺序进行存储,内存中连续且大小固定

   逻辑结构:除了首尾,中间的元素,有且只有一个一个前驱与后继。

特点:顺序并连续存储

           大小固定,提前申请好内存的空间

            表满不能存,表空不能删

             访问和查找比较方便

             插入和删除不太方便,需要移动元素

int insertList(List *pList,int pos,data_type item)
{
    //入参判断
    if(NULL == pList)
    {
        return MALLOCERROR;
    }
    //合法位置判断
    if(pos < 0 || pos > pList->count)
    {
        return POSERROR;
    }
    //判断表是否满
    if(pList->count == N)
    {
        return LISTFULL;
    }
    for(int i = pList->count-1;i >= pos;i--)
    {
        pList->arr[i+1] = pList->arr[i];//数据元素的移动
    }
    pList->arr[pos] = item;

    pList->count++;
    
    return OK;
}

 

int deleteItemList(List *pLsit,int pos,data_type *pData)
{
    if(pList == NULL)
    {
        return MALLOCERROR;
    }
    if(pos < 0 || pos > count-1)
    {
        return LISTEMPTY;
    }
    *pData = pList->arr[pos];
    for(int i = pos;i >= pLIst->count-1;i++)\
    {
        pList->arr[i] = pList->arr[i+1];
    }
    return OK;
}

 

int destoryList(List **ppList)
{
    if((*ppList == NULL) || (ppList == NULL))
    {
        return MALLOCERROR;
    }
    free(*ppList);
    *ppList = NULL;
    return OK;
}

day2

单链表

 节点data存放数据元素,而next是一个指针,指向后继节点(地址)

 

头节点:第一个数据域无效的节点

首节点:第一个数据域有效节点

尾节点:指针域为空的节点

int insertItemLink(linkNode *pHead,in pos,data_type item)
{
    if(NULL == pHead)
    {
        return LINKNULL;
    }
    linkNode *pNew = NULL;
    pNew = (linkNode *)malloc(sizeof(linkNode));
    if(NULL == pNew)
    {
        perror("malloc error");
        return MALLOCERROR;
    }
    memeset(pNew,0,sizeof(linkNode));
    
    pNew->data = item;
    linkNode *pt = NULL;
    pt = pHead;
    
    switch(pos)
    {
        case HEAD:
             pNew->next = pHead->next;
             pHead->next = pNew;
             break;
        case TAIL:
             while(pt->next != NULL)
             {
                pt = pt->next;   
             }
             pt->next = pNew;
             break;
        default:
             for(int i = 1;i <= pos-1;i++)
             {
                  if(NULL == pt)
                  {
                        free(pNew);
                        PNew = NULL;
                        return POSERROR;
                  }
                  pt = pt->next;  //游标移动到要插入位置的前一个位置停下
             }
             //先对pNew的指针域进行赋值,保护好要插入节点后面的节点地址
             pNew->next = pt->next;
             pt->next = pNew;
    }
}
int deleteItenLink(linkNode *pHead,int pos,data_type *pData)
{
    if(NULL == pHead)
    {
        return LINKNULL;
    }
    linkNode *pd = NULL;
    linkNode *pt = NULL;
    pd = pHead->next; //指向首节点
    pt = pHead;       //指向头节点
    switch(pos)
    {
    case HEAD:
         *pData = pd->data;
         pHead->next = pd->next;
         free(pd);
         pd = NULL;
         break;
    case TAIL:
         while(pd->next != NULL)
         {
             pt = pd;
             pd = pd->next;
         }
         *pData = pd->data;
         pt->next = NULL;
         free(pd);
         pd = NULL;
         break;
    default:
            //pd指向要删除的节点本身
            //pt指向要删除节点的前一个节点
         for(int i = 1;i <= pos+1;i++)
         {
               pt = pd;
               pd = pd->next;
         }
         *pData = pd->data;
         pt->next = pd->next;
         free(pd);
         pd = NULL;
        }
        return OK;
}
int destoryLinkNode(linkNode *ppHead) 
//*ppHead------->pHead    ppHead------->&pHead
{
    if((NULL == ppHead) || (NULL == *ppHead))
    {
        perror("malloc error");
        return LINKNULL;
    }
    while(1)
    {
    linkNode *pd = NULL;
    pd = (*ppHead)->next;

    if(NULL == pd)
    {
        break;
    }
    (*ppHead)->next = pd->next;
    free(pd);
    pd = NULL;
    }
    free(*ppHead);
    *ppHead = NULL;
    return OK;
}

 day3

int  reverse(linkNode *pHead)
{
    if(NULL == pHead)
    {
        return LINKNULL;
    }
    //先把原来的链表剪断
    //L1:带头节点的空链表
    //L2:不带头节点的链表
    linkNode *pFirst = NULL;
    pFirst = pHead->next;
    pHead->next = NULL;

    linkNode *pNew = NULL;//y用于指向要插入的节点地址
    
    
    //将L2中的节点头部插入到L1中
    while(1)
    {
        pNew = pFirst;
        if(NULL == pNew)
        {
            break;
        }
        pFirst = pFirst->next;
        
        //头部插入
        pNew->next = pHead->next;
        pHead->next= pNew;
    }
    return OK;
}

双链表

 struct dbLinkNode *pre;

 struct dbLinkNode *next;

插入

pNew->data = item;

dbLinkNode *pTemp = NULL;

pTemp = pHead;

//头插

pNew->pre = pHead;

pNew->next = pHead->next;

if(NULL != pHead->next)

{

        pHead->next = pNew; 

}

pHead->next = pNew;

//尾插

//中间插入

for(int i = 0;i <= pos-1;i++)

{

        pTemp = pTemp->next;

}

//先保护好要插入的节点后面的节点

·pNew->next = pTemp->next;

pNew->pre = pTemp;

if(pTemp->next != NULL)

{

        pTemp->next->pre = pNew;

}

pTemp->next = pNew;

栈:限制在一段进行插入和删除的线性表(先进后出)

顺序栈  链式栈

操作的话只能在栈顶操作

入栈:增加元素   出栈:删除元素

经典面试题:

 顺序栈:

typedef struct stack

{

        data_type arr[N]; //顺序且连续,大小固定

        int top;        //定义栈顶元素下标,top == -1 栈空  top == N 栈满

}Stack;

链式栈:插入操作和删除操作均在链表头部进行,链表尾部就是栈底,栈顶指针就是头指针。

day4

队列:先进先出、只允许在队尾插入,队头删除。

typedef  struct queue

{

        data_type arr[N];

        int front;

        int rear;//一般情况下,将rear以及front置为有效元素的前一个元素,   front == rear 时,队空

}Queue;

空队:pQueue->front == pQueue->rear;

入队:pQueue->rear = (pQueue->rear+1)% N;       pQueue->arr[pQueue->rear] = item;

出队:pQueue->front = (pQueue->front+1)% N;        *pData= pQueue->arr[pQueue->front];

(只能在队头出队)

未来解决循环队列中满队的问题,空出一个位置

案例:使用两个栈模拟一个队列

//入栈

printf("push:\n");

while(1)

{

        scanf("%d",&item);

        if(push(ps,item) == SKFULL)

        {

                break;

        }

}

printf("pop after and push again:\n");

//出栈再进栈

while(1)

{

        if((pop(ps,&item) == SKEMPTY) || push(pr,item) == SKFULL))

        {

                break;

        }

printf("%-5d",item);

}

printf("\n");

//再出栈

printf("pop again:\n");

while(1)

{

        if(pop(pr,&item) == SKEMPTY)

        {

                break;

         }

        printf("%-5d",item);

}

printf("\n");

day5 

一.树

1.树:只有一个根节点  ,其余的节点不能相交

根没有前驱,叶没有后继

2.度数:一个节点子树的个数

3.树叶:度数为o   在最后得(终端节点)

4.边数:

5.深度:树的节点最大值

A:度数2   这个树的度数:   树叶:D,E,F     边数: 3, 4,3     深度:4

二.二叉树

1.二叉树要分左右孩子,一个的话也要分清楚

2.二叉树最多俩子节点    分左右子树

性质:

1.第i层上最多2^(i-1) 

2.深度为k 最多  2^k -1

3.在任意一课二叉树中,树叶的数目比度数为2的节点的数目多1   n0=n2+1

eg、具有10个叶节点的二叉树有( )个度数为2的节点

A.8  B.9  C.10  D.11

10 = n2 + 1  n2= 9

4.满二叉树

5.完全二叉树:对于一课满二叉树,从下往上,从右往左,依次去掉若干个节点形成的数

6.顺序存储

7.链式存储

typedef struct treeNode

{

        struct treeNode *lChild;

        data_type data;

        struct treeNode *rChild;

} Tree;

8.遍历

前序遍历:根左右

中序遍历:左根右

后序遍历:左右根

void midOrder(Tree *pBoot)

{

        if(NULL == pBoot)

        {

                return;

        }

        midOrder(pBoot->lChild);

        printf("%d",pBoot->data);

        midOrder(pBoot->rChild);

 }

赫夫曼树:带权路径长度最短的树

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值