数据结构总结

本文深入讲解了多种数据结构,包括顺序表、单链表、双链表、栈、队列和二叉树的实现与操作,如初始化、插入、删除、遍历等,以及内核链表的特殊操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、顺序表
        typedef struct ARRAY //用于管理顺序表的数据类型
        {
            int * parr;//顺表的起始地址
            int len;//表示能够存储的数据节点的个数
            int cnt;//已经使用了的表项个数    
        }ARR,*PARR;

        void init_seq_list(PARR p,int length)//初始化一个顺序表
        {
            p->parr = malloc(sizeof(int)*length);
            if(p->parr == NULL)
            {
                printf("malloc failed!\n");
                exit(-1);
            }
            p->len = length;
            p->cnt = 0;
        }
        
        bool is_full(PARR p)  //判断表满
        {
            if(p->cnt == p->len)
                return true;
            else
                return false;
        }


        bool insert_seq_list(PARR p,int pos,int data)//顺序表的插入
        {
            int i;
            if(is_full(p))
                return false;
            if((pos <1) || (pos > (p->cnt + 1)) )
                return false;
            for(i = p->cnt -1;i>=pos-1;i--)
            {
                p->parr[i+1]=p->parr[i];
            }
            p->parr[pos-1] = data;
            p->cnt++;
            return true;    
        }

        bool is_empty(PARR p)//判断表空
        {
            if(p->cnt == 0)
                return true;
            else
                return false;
        }
        
        void show_seq_list(PARR p)//顺序表的遍历
        {
            int i;
            if(is_empty(p))
            {
                printf("没得show\n");
                return;
            }
            for(i=0;i< p->cnt;i++)
                printf("%d\t",p->parr[i]);
            printf("\n");
        }

        bool del_seq_list(PARR p,int pos,int *pdata)//顺序表的删除
        {
            int i;
            if(is_empty(p))
            {
                printf("没得删\n");
                return false;
            }
            if(pos < 1 || pos > p->cnt)
                return false;    
            *pdata = p->parr[pos-1];    
            for(i=pos;i<p->cnt;i++)
                p->parr[i-1]=p->parr[i];
            p->cnt--;
            return true;
        }
    2、单链表(循环)
        typedef struct node
        {
            int data;//数据域
            struct node *next;

        }NODE,*PNODE;

        PNODE init_link_list(void)//单链表初始化
        {
            PNODE phead = malloc(sizeof(NODE));
            if(phead == NULL)
            {
                exit(-1);
                //return phead;
            }
            phead->next = phead;
                
            return phead;
        }

        PNODE new_node(int dat)
        {
            PNODE pnew =malloc(sizeof(NODE));
            if(pnew == NULL)
                return pnew;
            pnew->data = dat;
            pnew->next = NULL;
            return pnew;
        }

        bool insert_node_tail(PNODE phead,PNODE pnew)// 把地址为pnew的节点插入到单向循环链表的尾部(头节点前面)
        {
            if(pnew == NULL || phead == NULL)
                return false;
            PNODE p = phead->next;
            while(p->next != phead)
                p = p->next;
            pnew->next = phead;
            p->next = pnew;
            return true;
        }

        bool is_empty(PNODE phead)//判断链表为空,没有满的情况
        {
            if(phead->next == phead)
                return true;
            else
                return false;
        }

        void show_list(PNODE phead)//链表的遍历
        {
            PNODE p = NULL;
            if(is_empty(phead))
            {
                printf("list is empty!\n");
                return;
            }
            p = phead->next;
            while(p != phead)//遍历
            {
                printf("%d\t",p->data);
                p = p->next;
            }
            printf("\n");
        }

        bool del_node(PNODE phead,PNODE pdel)//单向循环链表的删除
        {
            PNODE p;
            if(phead == pdel || phead == NULL || pdel == NULL)
                return false;
            //p = phead->next
            p = phead;
            while(p->next != phead)
            {
                if(p->next == pdel )
                    break;
                p = p->next;
                //ptmp= ptmp->next;    
            }
            if(p->next != pdel)
                return false;
            //删除节点
            p->next = pdel->next;
            pdel->next = NULL;
            //free(pdel);
            return true;
        }
    3、双链表
        typedef struct node
        {
            int data;//数据域
            struct node *next;
            struct node *prev;
        }NODE,*PNODE;

        PNODE init_dc_list(void)//双向循环链表的初始化
        {
            PNODE phead = malloc(sizeof(NODE));
            if(phead ==NULL)
                return phead;
            phead->prev = phead;
            phead->next = phead;
            return phead;
        }

        PNODE new_node(int dat)//新建一个节点
        {
            PNODE pnew = malloc(sizeof(NODE));
            if(pnew ==NULL)
                return pnew;
            pnew->data = dat;
            pnew->prev = pnew;
            pnew->next = pnew;
            return pnew;
        }

        //把地址为pnew的节点插入到双向循环链表的尾部(头节点的前面)
        bool list_add_tail(PNODE phead,PNODE pnew)
        {
            if(pnew == NULL || phead == NULL)
                return false;
            phead->prev->next = pnew;
            pnew->prev = phead->prev;
            phead->prev = pnew;
            pnew->next = phead;
            return true;
        }

        void show_dc_list(PNODE phead)//双向循环链表的遍历
        {
            PNODE p;
            if(phead == NULL)
                return;
            p = phead->prev;
            while(p != phead)
            {
                printf("%d\t",p->data);
                p = p->prev;
            }
            printf("\n");
        }

        //删除双向循环链表中地址为pdel的节点
        bool del_dc_node(PNODE phead,PNODE pdel)
        {
            PNODE p;
            if(phead == pdel || phead == NULL || pdel == NULL)
                return false;
            p = phead->next;
            while(p != phead)
            {
                if(p == pdel )
                    break;
                p = p->next;    
            }
            if(p != pdel)
                return false;    
            pdel->prev->next = pdel->next;
            pdel->next->prev = pdel->prev;
            pdel->next = pdel->prev = NULL;
            return true;
        }

        PNODE find_node(PNODE phead,int dat)//双向循环链表的查找
        {
            if(phead == NULL)
                return phead;
            PNODE p = phead->next;
            while(p != phead)
            {
                if(p->data == dat)
                    break;
                p = p->next;
            }    
            if(p == phead)
            {
                printf("dat is not in link list\n");
                return NULL;
            }
            return p;
        }
    4、栈(链栈)
            typedef struct node
            {
                int data;//数据域
                struct node *next;
            }NODE,*PNODE;

            typedef struct stack//管理链式栈的数据类型
            {
                PNODE pbot;
                PNODE ptop;
            }ST,*PST;


            PST init_link_stack(void)//链栈的初始化
            {
                PST p = malloc(sizeof(ST));
                if(p == NULL)
                {
                    return p;
                }
                p->ptop  = malloc(sizeof(NODE));
                if(p->ptop == NULL)
                {
                    free(p);
                    return NULL;
                }
                p->pbot = p->ptop ;    
                p->ptop->next = NULL;
                return p;
            }

            bool push(PST ps,int dat)//入栈
            {
                PNODE pnew = malloc(sizeof(NODE));
                if(pnew == NULL)
                    return false;
                pnew->data = dat;
                pnew->next = NULL;
                ps->ptop->next = pnew;
                ps->ptop = pnew;
                return true;
            }

            bool is_empty(PST ps)//栈空
            {
                if(ps->ptop == ps->pbot)
                    return true;
                else
                    return false;
            }

            bool pop(PST ps,int * pdata)//出栈
            {
                if(is_empty(ps))
                    return false;
                *pdata = ps->ptop->data;
                PNODE p = ps->pbot;
                while(p->next != ps->ptop )
                {
                    p = p->next;
                }
                ps->ptop = p;
                free(p->next);
                ps->ptop->next = NULL;
                return true;
            }

            void show_stack(PST ps)//栈的遍历
            {
                PNODE p = NULL;
                if(is_empty(ps))
                {
                    printf("stack is empty!\n");
                    return;
                }
                PNODE ptmp = ps->ptop;
                
                while(ptmp != ps->pbot)
                {
                    PNODE p = ps->pbot;
                    while(p->next != ptmp )
                    {
                        p = p->next;
                    }
                    printf("%d\t",ptmp->data);
                    ptmp = p;
                }
                printf("\n");
            }
    5、队列(循环队列)
            typedef struct queue //用于管理循环队列的数据类型
            {
                int * pq;//循环队列的起始地址
                int f;//队头下标
                int r;//队尾下标    
            }QUE,*PQUE;

            PQUE init_queue(void)//初始化空的循环队列,大小为size(节点的个数)
            {
                PQUE p = malloc(sizeof(QUE));
                if(p == NULL)
                    return p;
                p->pq = malloc(SIZE * sizeof(int));
                if(p->pq == NULL)
                {
                    free(p);
                    return NULL;
                }
                p->f = p->r = 0;    
                return p;
            }

            bool is_full(PQUE p)//队列满
            {
                if( p->f  ==  ((p->r + 1) % SIZE) )
                    return true;
                else
                    return false;
            }

            bool en_queue(PQUE p,int dat)//把dat入队(队尾)
            {
                if(p == NULL)
                    return false;
                if(is_full(p))
                    return false;
                p->pq[p->r] = dat;
                p->r = (p->r + 1)%SIZE;
                return true;
            }

            bool is_empty(PQUE p)//队列空
            {
                if(p->f == p->r)
                    return true;
                else
                    return false;
            }

            bool out_queue(PQUE p,int * pdata)//出队
            {
                if(p == NULL)
                    return false;
                if(is_empty(p))
                    return false;
                *pdata = p->pq[p->f];    
                p->f = (p->f + 1)%SIZE;
                return true;
            }

            bool show_queue(PQUE p)//队的遍历
            {
                if(is_empty(p))
                {
                    printf("没得show\n");
                    return false;
                }
                int i = p->f;
                while(i != p->r)
                {
                    printf("%d\t",p->pq[i]);
                    i = (i+1)%SIZE;
                }
                printf("\n");
                return true;
            }
    6、内核链表
        节点设计
            struct stu
            {
                int age;
                。。。
                struct list_head mbr;
            };
            其中
            struct list_head {
                struct list_head *next, *prev;
            };

        内核链表操作常用的函数或宏
            初始化内核链表
                INIT_LIST_HEAD(ptr) //ptr为小结构体指针struct list_head *
            插入节点        //把地址为new的小结构体,插入到头节点的后面(首部)
                static inline void list_add(struct list_head *new, struct list_head *head)
                //把地址为new的小结构体,插入到头结点的前面(尾部)
                static inline void list_add_tail(struct list_head *new, struct list_head *head)
            删除/移动节点
                //删除地址为entry的内核链表节点
                static inline void list_del(struct list_head *entry)
                //把地址为list的节点移动到头结点的后面
                static inline void list_move(struct list_head *list,struct list_head *head)
                //把地址为list的节点移动到头节点的前面(尾部)
                static inline void list_move_tail(struct list_head *list,struct list_head *head)
            判断链表是否为空
                static inline int list_empty(struct list_head *head)
            由小结构体的地址ptr,获得大结构体的地址
                //ptr 为小结构体地址struct list_head * ,type为大结构体类型,member为小结构体在大结构体中的变量名
                list_entry(ptr, type, member) 
            遍历
                //向后遍历,pos为循环控制变量,pos类型为struct list_head * ,head为内核链表头结点的地址,类型struct list_head *
                #define list_for_each(pos, head)    for(pos = (head)->next; pos != (head); pos = pos->next)    
                //向前遍历
                #define list_for_each_prev(pos, head)   for(pos = (head)->prev; pos != (head); pos = pos->prev)
                //向后遍历的安全版,用于删除节点的场合,n为中间变量,类型为struct list_head *
                list_for_each_safe(pos, n, head)
            通过大结构体指针向后遍历,pos为循环控制变量,大结构体指针,pos类型为struct xxx *
                //head内核链表头结点地址,类型为小结构体指针struct list_head*
                //member为小结构体在大结构体中的变量名
                list_for_each_entry(pos, head, member)
                //通过大结构体指针向后遍历的安全版,用于删除节点的场合
                //n是中间变量,类型为大结构体指针struct xxx *
                list_for_each_entry_safe(pos, n, head, member)
                
                
            struct stu
            {
                int age;
                struct list_head mbr;
            };

            //创建一个空的内核链表,返回大结构的地址
            struct stu * create_klist(void)
            {
                struct stu * phead = malloc(sizeof(struct stu));
                if(phead == NULL)
                    return phead;
                INIT_LIST_HEAD(&(phead->mbr));
                return phead;
            }

            //构造一个新节点,返回大结构体的地址
            struct stu * new_node(int data)
            {
                struct stu * pnew = malloc(sizeof(struct stu));
                if(pnew == NULL)
                    return pnew;
                pnew->age = data;
                INIT_LIST_HEAD(&(pnew->mbr));
                return pnew;
            }

            bool insert_knode_tail(struct stu* phead,struct stu* pnew)//插入一个节点
            {
                if(phead == NULL || pnew == NULL)
                    return false;
                list_add_tail(&(pnew->mbr), &(phead->mbr));
                return true;
            }

            void show_klist(struct stu* phead)//遍历内核链表
            {
                struct stu * p;
                struct list_head * pos;
                list_for_each(pos, &(phead->mbr))
                {
                    p=list_entry(pos, struct stu, mbr);
                    printf("%d\t",p->age);
                }
                printf("\n");
            }


            bool del_knode(struct stu *phead,int data)//删除节点
            {
                if(phead == NULL)
                    return false;
                struct stu * pos,*n;
                list_for_each_entry_safe(pos, n, &(phead->mbr), mbr)
                {
                    if(pos->age == data)
                        break;
                }
                if(pos == phead)
                    return false;
                list_del(&(pos->mbr));
                return true;
            }
    7、二叉树(先序遍历)    
            二叉树的遍历
                先序遍历:先访问根节点,然后先序遍历左子树,最后先序遍历右子树
                中序遍历:先中序遍历左子树,再访问根节点,最后中序遍历右子树
                后序遍历:先后序遍历左子树,然后后序遍历右子树,最后访问根节点
                typedef struct node
                {
                    char data;//数据域
                    struct node *plch;//左指针
                    struct node *prch;//右指针
                }NODE,*PNODE;
                PNODE init_btree(void)//初始化二叉树
                {
                    PNODE pa,pb,pc,pd,pe,pf;
                    pa = malloc(sizeof(NODE));
                    pb = malloc(sizeof(NODE));
                    pc = malloc(sizeof(NODE));
                    pd = malloc(sizeof(NODE));
                    pe = malloc(sizeof(NODE));
                    pf = malloc(sizeof(NODE));
                    
                    pa->plch = pb;
                    pa->prch = pc;
                    
                    pb->plch = pd;
                    pb->prch = pe;
                    
                    pc->plch = pf;
                    pc->prch = NULL;
                    
                    pd->plch = NULL;
                    pd->prch = NULL;
                    
                    pe->plch = NULL;
                    pe->prch = NULL;
                    
                    pf->plch = NULL;
                    pf->prch = NULL;
                    
                    pa->data = 'a';
                    pb->data = 'b';
                    pc->data = 'c';
                    pd->data = 'd';
                    pe->data = 'e';
                    pf->data = 'f';
                    
                    return pa;
                }


                void pre_show(PNODE proot)//递归遍历二叉树
                {
                    if(proot != NULL)
                    {
                        printf("%c\t",proot->data);//先访问根节点
                        if(proot->plch != NULL)
                            pre_show(proot->plch);//先序遍历左子树
                        if(proot->prch != NULL)
                            pre_show(proot->prch);//先序遍历右子树
                    }
                }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值