数据结构

总结以下最近一些遇到的一些问题,一般在开发中数据结构用的页比较多,一开始都不知道如何使用,什么时候用它,什么时候不用它,先讲解一下数据结构的定义吧:
定义:数据结构其实就是另外一种存储数据的方式,和数组是有区别的,数组是顺序存储,链表是随机存储,有线性链表,链式存储。
方式: 单链表,双链表,双向循环链表,二叉树,队列,栈,树,
第一个是链表:是非顺序,非连续的存储数据

数据结构_第1张图片简单的链表插入和删除
第一个弄明白这个过程
一步:链表包含的两个变量,一个是指向前一个节点的指针域和一个是指向后一个节点的指针域
创建一个头结点函数
struct list_head {
struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name)
struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}

append====

static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head
*head)
{
__list_add(new, head->prev, head);
}

有插入会想到要在哪里删除你想要的数据
#define list_entry(ptr, type, member)
container_of(ptr, type, member)

#define list_for_each_entry(pos, head, member)
for (pos = list_entry((head)->next, typeof(*pos), member);
&pos->member != (head);
pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each(pos, head)
for (pos = (head)->next; pos != (head); pos = pos->next)

====

#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})

========

#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE )0)->MEMBER)
#endif
#endif /
KERNEL */
这是一个简单的链表变成
2 单链表的数据
插入:只能往前或者往后插入数据,不能同时在两边插入数据。
创建一个结点(两个变量,一个数据域和一个指针域)指针域指向后继的结点
插入-》遍历-》查找-》删除
//带头节点的单链表操作
#include
#include

struct node{
int data; //数据域

struct node  *next;//指向后继节点的指针

};

//头部追加
int appendHead(struct node *h,int num);
//尾部追加
int appendTail(struct node *h,int num);

//*e===>end 记录末尾节点 初始值从头节点开始
int appendTail_t(struct node **e,int num);

/*

  • 有序插入:
  • 从小到大:应插入在第一次比新节点的值大的节点之前 或者最末尾
  • 从大到小:应插入在第一次比新节点的值小的节点之前 或者最末尾
  • 应用快慢指针
    */
    int sortInsert(struct node *h,int num);
    //遍历
    void travelList(const struct node *h);
    //查找 返回数据节点指针 没有找到返回NULL
    struct node *searchNode(const struct node *h,int key);

//删除一个节点 如果有多个数据匹配 则删除第一个
void deleteOneNode(struct node *h,int key);
//删除数据匹配的节点
void deleteNode(struct node *h,int key);

int main(void)
{
//头节点 空链
struct node head={.next=NULL};

struct node  *end=&head;//记录最末尾的节点

int num;

printf("input int number(-1 over)\n");
while(1)
{
    scanf("%d",&num);
    if(num==-1)   break;

    //num插入到链表前面 成为当前第一个数据节点
    //appendHead(&head,num);
    
    //num插入到链表末尾 成为当前最后一个数据节点
    //appendTail(&head,num);
    //appendTail_t(&end,num);
    
    //有序插入
    sortInsert(&head,num);
}

travelList(&head);

struct node *tmp;
tmp=searchNode(&head,5);
if(tmp==NULL){
    printf("Not Found.\n");
}else{
    printf(">>>>>>%d\n",tmp->data);
}

//删除一个节点 如果有多个数据匹配 则删除第一个
//deleteOneNode(&head,5);
//删除数据匹配的节点 
deleteNode(&head,5);

travelList(&head);
return 0;

}
int appendHead(struct node *h,int num)
{
struct node *newNode;
//分配数据节点
newNode=malloc(sizeof(struct node));
if(NULL==newNode) return -1;
//数据域赋值
newNode->data=num;

//修改新节点的指针指向原来头节点中指针所指向的位置
newNode->next=h->next;
//修改头节点中指针 指向 新节点
h->next=newNode;

return 0;

}

int appendTail(struct node *h,int num)
{
struct node *newNode;

newNode=malloc(sizeof(struct node));
if(newNode==NULL)   return -1;

//数据域赋值
newNode->data=num;
//新节点指针 指向 NULL
newNode->next=NULL;

#if 1
struct node **t;
t=&h->next;//指向头指针

while(*t!=NULL)
{
   t=&(*t)->next;//指向下一个节点的next指针
} 

*t=newNode;

#elif 0
/*

  • 头节点也是同类型的节点 包括头节点节所有数据节点在内

  • 找出某节点指针next指向NULL的节点 修改其next指针 指向新节点
    */
    struct node *end;
    end=h;
    while(end->next!=NULL)
    {
    end=end->next;
    }
    end->next=newNode;
    #else
    if(h->next==NULL)//空链表
    {
    h->next=newNode;
    }
    else//非空链表 找到尾节点 修改尾节点 的指针 指向 新节点
    {
    struct node *end;

     end=h->next;
     while(end->next!=NULL)
     {
         end=end->next;
     }
     end->next=newNode;
    

    }
    #endif //
    return 0;
    }

//*e===>end 记录末尾节点 初始值从头节点开始
//用于连续插入提高效率 只有开始需要超找末尾节点 之后直接记录
int appendTail_t(struct node **e,int num)
{
struct node *newNode;

newNode=malloc(sizeof(struct node));
if(newNode==NULL)   return -1;

//数据域赋值
newNode->data=num;
//新节点指针 指向 NULL
newNode->next=NULL;

while((*e)->next!=NULL)
{
   *e=(*e)->next;
}

(*e)->next=newNode;
*e=newNode;//更新指向新的末尾节点

return 0;

}
/*

  • 有序插入:

  • 从小到大:应插入在第一次比新节点的值大的节点之前 或者最末尾

  • 从大到小:应插入在第一次比新节点的值小的节点之前 或者最末尾

  • 应用快慢指针
    */
    int sortInsert(struct node *h,int num)
    {
    struct node *newNode,*t,*s;//s:慢指针 t:快指针

    newNode=malloc(sizeof(struct node));
    if(newNode==NULL) return -1;
    newNode->data=num;

    s=h;
    t=h->next;
    while(t!=NULL)
    {
    if(t->data >= newNode->data)
    {
    break;
    }
    //
    s=t;
    t=t->next;
    }
    //插入在s t之间
    newNode->next=t;
    s->next=newNode;
    return 0;
    }

//遍历
void travelList(const struct node *h)
{
struct node *t;

t=h->next;
while(t!=NULL)
{
    printf("%d ",t->data);
    t=t->next;
}
putchar('\n');

}
struct node *searchNode(const struct node *h,int key)
{
struct node *t;

t=h->next;
while(t!=NULL)
{
    if(t->data==key)
        return t;

    t=t->next;
}
return NULL;

}

/*

  • 删除一个节点 如果有多个数据匹配 则删除第一个

  • 由于删除一个节点需要修改其 前继节点的指针 而访问不可逆 所有快慢指针组合

  • t快指针用于遍历访问数据 s慢指针总是指向 t的 前继节点
    */
    void deleteOneNode(struct node *h,int key)
    {
    struct node *t,*s;

    s=h;
    t=h->next;
    while(t!=NULL)
    {
    if(t->data==key)//条件匹配 删除
    {
    s->next=t->next;
    free(t);
    break;
    }

     s=t;
     t=t->next;
    

    }
    }
    //删除数据匹配的节点
    void deleteNode(struct node *h,int key)
    {
    #if 1
    struct node **t,*cur;
    t=&h->next;
    while(*t!=NULL)
    {
    cur=*t;
    if(cur->data==key)//删除
    {
    t=cur->next;//断链 pos->next = p->next; 如果不取地址 不解引用 就是单纯的给t赋值
    free(cur);
    continue;
    }

    t=&cur->next;//t=&(*t)->next;
    

    }
    #else
    struct node *t,*s;

    s=h;
    t=h->next;
    while(t!=NULL)
    {
    if(t->data==key)//条件匹配 删除
    {
    s->next=t->next;
    free(t);
    t=s;
    }

     s=t;
     t=t->next;
    

    }
    #endif
    }
    因为时间有限暂时写到这里后续还会补充后面的链表的知识

你可能感兴趣的:(数据结构)