顺序表&&链表总结

线性表

1.线性表是一种数据内部的逻辑关系,与存储形式无关

2.线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)

3.顺序表和链表都称为线性表

链表与顺序表差异

​ 既然顺序存储中的数据因为挤在一起而导致需要成片移动,那很容易想到的解决方案是将数据离散地存储在不同内存块中,然后在用来指针将它们串起来。这种朴素的思路所形成的链式线性表,就是所谓的链表。

1.顺序表

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int dataType;//给int起别名dataType

// 定义顺序表管理结构体,名字为sequeList
typedef struct sequeList
{
    int cap; // 顺序表总大小
    int last; // 顺序表元素下标
    dataType *data; // 指向顺序表的首元素地址
}sequeList;

// 初始化顺序表
sequeList *init_seque(int cap)
{
    if(cap <= 0)
        return NULL;
    // 给顺序表管理结构体分配空间
    sequeList *head = malloc(sizeof(sequeList));
    if(head == NULL)
        return NULL;
    
    head->cap = cap;
    head->last = -1;
    head->data = calloc(cap,sizeof(dataType));
    if(head->data == NULL)
        return NULL;

    return head;
}

// 判断表是否满
bool isFull(sequeList *head)
{
    if(head->cap == head->last+1)
        return true;
    return false;
}

// 判断表为空
bool isEmpty(sequeList *head)
{
    if(head->last == -1)
        return true;
    return false;
}

// 插入数据
bool insert(sequeList *head, dataType data)
{
    if(head == NULL)
        return false;
    // 判断数据是否已满
    if(isFull(head))
        return false;

    head->data[++head->last] = data;
    return true;
}


void maopao(sequeList *head)
{
 
    for (int i=0;i< head->last;i++)
    {
        for(int j=0;j< head->last-i;j++)
        {
            if(head->data[j]>head->data[j+1]) 
            {
                int temp=head->data[j];
                head->data[j]=head->data[j+1];
                head->data[j+1]=temp;

            }
        }
    }
}
sequeList *removeData(sequeList *head, dataType data)
{
    if(isEmpty(head))
        return NULL;
    // 找需要删除的数据下标
    int i = 0;
    for(;i <= head->last; i++)
    {
        if(head->data[i] == data)
        {
            break;
        }
    }
    // 后面的进行覆盖
    for(int j = i; j < head->last; j++)
    {
        head->data[j] = head->data[j+1];
    }
    head->last--;
    return head;
}
// 显示插入的数据
void showList(sequeList *head)
{
    for(int i = 0;i < head->last+1; i++)
    {
 
        printf("%d\t",head->data[i]);

    }
}

// 销毁顺序表
void deStory(sequeList *head)
{
    free(head->data);
    head->data = NULL;
    free(head);
    head = NULL;
}
int main(int argc, char const *argv[])
{
    // 初始化表
    sequeList *head = init_seque(10);
    if(head == NULL)
    {
        printf("init failed\n");
        return -1;
    }
    dataType data,a;
    printf("输入数据到负数结束:\n");
    while(1)
    {
        
        scanf("%d",&data);
        if(data<0)
        {
            a=-data;
            break;
        }
        
        // 将输入插入到表
        insert(head,data);
    
    }

    removeData(head,a);



    maopao(head);
    showList(head);
    // 销毁顺序表
    deStory(head);
    return 0;
}

1.优点

​ 不需要多余的信息来记录数据的关系,存储密度高

​ 所有数据顺序存储在一片连续的内存中,支持立即访问任意一个随机数 据,比如上述顺序表中第i个节点是s->data[i]

2.缺点

​ 插入、删除时需要保持数据的物理位置反映其逻辑关系,需要成片移动数据

​ 当数据节点较多时,需要一整片较大的连续内存空间

​ 当数据节点数量变化剧烈时,内存的释放和分配不灵活

2.链表

链表的增删改和销毁

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef int dataType;

// 数据节点
struct node 
{
    dataType data;
    struct node *next;
};

// 头节点,管理结构体
struct headNode
{
    struct node *first; // 指向首节点
    struct node *tail; // 指向尾节点
    int nodeNumber; // 链表节点个数
};

struct headNode *init_headNode(void)
{
    struct headNode *head = malloc(sizeof(struct headNode));
    if(head == NULL)
        return NULL;
    
    head->first = NULL;
    head->tail = NULL;
    head->nodeNumber = 0;

    return head;
}

// 创建新节点
struct node *create_newNode(dataType data)
{
    struct node *pnew = malloc(sizeof(struct node));
    if(pnew == NULL)
        return NULL;
    pnew->data = data;
    pnew->next = NULL;
    return pnew;
}

// 创建带头节点的单向链表
struct headNode* create_list(void)
{
    // 初始化管理结构体
    struct headNode *head = init_headNode();
    if(head == NULL)
    {
        printf("init head node failed\n");
        return NULL;
    }

    while(1)
    {
        dataType data;

        if(scanf("%d",&data) == 0)// 退出
        {
            while(getchar()!='\n');
            break;
        }    

        // 创建新节点
        struct node *pnew = create_newNode(data); 
        // 从无到有
        if(head->first == NULL)
        {
            head->first = pnew;
            head->tail = pnew;
        }
        else // 从少到多
        {
            // 头插法
            // pnew->next=head->first;
            // head->first=pnew;
            // 尾插法
            head->tail->next=pnew;
            head->tail=pnew;
        }
        head->nodeNumber++;
    }
    return head;

}
//更新节点
struct headNode* updata(struct headNode *head,dataType data,dataType newdata)
{
    //找节点
    struct node *p=head->first;
    while(p)
    {
        if(p->data==data)
        {
            p->data=newdata;
            break;
        }
        else
        {
            p=p->next;
        }
    }
    if(p==NULL)
    {
        printf("没找到要更新的数据\n");
    }
    return head;
}
//删除节点
struct headNode* delete(struct headNode *head,dataType data)
{
     // 找节点
    struct node *p = head->first;
    struct node *pre=NULL;
    while (p)
    {
        if(p->data == data)
        {
            break;
        }
        else // 继续找
        {
            pre=p;
            p = p->next;
        }
    }
    if(p == NULL)
    {
        printf("没有需要删除的数据\n");
    }
    else if(head->first->data==p->data)
    {
        head->first=p->next;
        head->nodeNumber--;  
        free(p);
        p=NULL;
    }
    else//在中间
    {
        pre->next=p->next;
        head->nodeNumber--;  
        free(p);
        p=NULL;
    } 
    
    return head;
}
//添加节点
struct  headNode *add_node(struct headNode *head,dataType data,dataType newdata)
{
    //创建新节点
    struct node *pnew=create_newNode(newdata);
    if(pnew==NULL)
        return NULL;
    struct node *p=head->first;
    struct node *pre=NULL;
    //找插入位置
    while(p)
    {
        if (p->data==data)
            break;
        else
        {
            pre=p;
            p=p->next;
        }
    }
    //如果没有找到
    if(p==NULL)
        head->tail=pnew;
    //如果在头部
    else if(head->first->data==p->data)
    {
        pnew->next=head->first;
        head->first=pnew;
    }
    else//在其他位置
    {
        pnew->next=p;
        pre->next=pnew;
    }
    head->nodeNumber++;
    return head;
}
//冒泡排序
struct headNode * bubble(struct headNode *head)
{
    
    for(int i = 0; i < head->nodeNumber-1; i++)
    {
        struct node *p=head->first;
        // 将每一遍的数据比较后进行交换
        for(int j = 0; j < head->nodeNumber-i-1; j++)
        {
            if((p->data)   >   (p->next->data))
            {
                int temp = p->data;
                p->data =p->next->data;
                p->next->data = temp;
            }
            p=p->next;
        }

    }
    return head;
}
//反转链表
struct headNode * reverse_list(struct headNode *head)
{
    // struct node *prev = NULL;
    // struct node *curr = head->first;
    // struct node *next = NULL;

    // while (curr != NULL)
    // {
    //     next = curr->next;
    //     curr->next = prev;
    //     prev = curr;
    //     curr = next;
    // }

    // head->first = prev;
    // return head;
    //拆合
    struct node *p=head->first;
    struct node *pnew=NULL;
    head->first=NULL;
    head->tail=NULL;
    while(p)
    {
        //拆
        pnew=p;
        p=p->next;
        pnew->next=NULL;
        //合
        if (head->first==NULL)
        {
            head->first=pnew;
            head->tail=pnew;
        }
        else
        {
            pnew->next=head->first;
            head->first=pnew;
        }

    }
    return head;
}
//合并
struct headNode *merge_tow_list(struct headNode *head1,struct headNode *head2)
{
    struct  node *pA= head1->first;
    struct  node *pB= head2->first;
    struct headNode *head=malloc(sizeof(struct headNode));
    struct node *pnew =head->first;
    head->first=NULL;
    head->tail=NULL;
    head->nodeNumber=head1->nodeNumber+head2->nodeNumber;
    while(pA&&pB)
    {
        if(pA->data<pB->data)
        {
            pnew=pA;
            pA=pA->next;
            pnew->next=NULL;

        }  
        else
        {
            pnew=pB;
            pB=pB->next;
            pnew->next=NULL;

        }
        if(head->first==NULL)
        {
            head->first=pnew;
            head->tail=pnew;
        }
        else
        {
            head->tail->next=pnew;
            head->tail=pnew;
        }

    }

    if(pA!=NULL)
    {
        head->tail->next=pA;
        head->tail=head1->tail;
    }
    else
    {
        head->tail->next=pB;
        head->tail=head2->tail;
    }
    //释放
    head1->first=NULL;
    head1->tail=NULL;
    head2->first=NULL;
    head2->tail=NULL;
    free(head1);
    free(head2);

    return head;
}
// 判断链表是否为空
bool isEmpty(struct headNode *head)
{
    if(head->nodeNumber == 0)
        return true;
    return false;
}
// 显示链表
void show_list(struct headNode *head)
{
    if( isEmpty(head))
        return;

    for(struct node *p = head->first; p != NULL; p =p->next)
    {
        printf("%d\t",p->data);
    }
    printf("\n");
    printf("链表已有%d个节点\n",head->nodeNumber);
}
// 销毁链表
struct headNode * distory_list(struct headNode *head)
{
    if(isEmpty(head))
        return false;
    
    // 逐一删除节点
    struct node *p = NULL;
    for(struct node *tmp = head->first;tmp != NULL; tmp = p)
    {
        p = tmp->next;
        free(tmp);
        head->nodeNumber--;
    }
    return head;
}
int main(int argc, char const *argv[])
{
    // 创建链表
    // struct headNode *head1= create_list();
    // if(head1==NULL)
    //     return -1;
   
    // struct headNode *head2= create_list();
    // if(head2==NULL)
    //     return -1;
    struct headNode *head= create_list();
    if(head==NULL)
        return -1;
    //更新节点
    // head=updata(head,5,8);
    // show_list(head);
    //删除节点
    // head=delete(head,1);
    // show_list(head);
    //添加节点
    head=add_node(head,8,6);
    show_list(head);
    //排序
    // head=bubble(head);
    // show_list(head);
    // 销毁链表
    // distory_list(head);
    //反转链表
    // head=reverse_list(head);
    // show_list(head);
    //合并两条有序链表
    // struct headNode *head=merge_tow_list(head1,head2);
    // show_list(head);
    return 0;
}

3.栈(先进后出)

顺序栈

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int dataType;

// 定义顺序栈管理结构体
typedef struct 
{
    dataType *data; // 指向顺序栈的首地址
    int size; // 顺序栈容量
    int top; // 栈顶
}seqStack;

// 初始化顺序栈
seqStack *init_stack(int size)
{
    seqStack *s = malloc(sizeof(seqStack));
    if(s == NULL)
        return NULL;

    s->data = calloc(size,sizeof(dataType));
    if(s->data == NULL)
        return NULL;

    s->size = size;
    s->top = -1;
    
    return s;
}

// 判断栈满
bool is_full(seqStack *s)
{
    return s->top == s->size-1;
}

// 判断栈为空
bool isEmpty(seqStack *s)
{
    return s->top == -1;
}

// 入栈
// bool push(seqStack *s,dataType data)
// {
//     // 判断是否栈满
//     if(is_full(s))
//         return false;

//     s->data[++s->top] = data;
//     return true;
// }
void push(seqStack *s,dataType data) 
{
    if (is_full(s)) 
    {
        printf("Stack is full.\n");
        return;
    }
    s->data[++s->top] = data;
}
// 取栈顶,不出栈
bool top(seqStack *s, dataType *data)
{
    if(isEmpty(s))
        return false;
    // 取栈顶元素
    *data = s->data[s->top];
    return true;
}

// 出栈
// bool pop(seqStack *s, dataType *data)
// {
//     if(!top(s,data))
//     {
//         return false;
//     }
//     s->top--;
//     return true;
// }
int pop(seqStack *s) 
{
    if (isEmpty(s)) 
    {
    printf("Stack is empty.\n");
    return -1;
    }
    return s->data[s->top--];
}
//打印栈
void printStack (seqStack *s) 
{
    if (isEmpty(s)) 
    {
        printf("Stack is empty.\n");
        return;
    }
    printf("Stack: ");
    for(int i=0;i<=s->top;i++)
    {
        printf("%d",s->data[i]);
    }
    printf("\n");
}

//输入数字或字母时,依次入栈,出栈
void stack(seqStack *s)
{
    char input;
    dataType data;

    while(1)
    {
   
        printf("请输入数字或字母:");
        scanf("%c",&input);
        getchar();
        if(input >= '0' && input <= '9')
        {
            data=input-'0';
            push(s, data);
  
        }
        else if(input >= 'a' && input <= 'z')
        {
            data=pop(s);
        }
        else
        {
            printf("输入错误\n");
            continue;
        }
        printStack (s);
    }
}

//十进制转八进制
void list(seqStack *s)
{

    int input,pro,a;
    scanf("%d",&input);
    getchar();
        
    do
    {

        a=input%8;
        push(s, a);
        input=input/8;

    } while (input!=0);
    printStack(s);

}   
int main(int argc, char const *argv[])
{
    seqStack *s = init_stack(10);
    if(s == NULL)
    {
        printf("init stack failed\n");
        return -1;
    }

    // 入栈
    // push(s,1);
    // push(s,2);
    // push(s,3);

    // dataType data;
    // // 弹栈
    // while (s->top != -1)
    // {
    //     pop(s,&data);
    //     printf("%d\t",data);
    // }
    // printf("\n");
   
    //输入数字或字母时,依次入栈,出栈
    // stack(s);
    list(s);
    return 0;
}

链式栈

//链式栈
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

typedef int dataType;

// 数据节点
typedef struct node
{
    dataType data;
    struct node *next; // 指向下一个node节点
}node;

// 链式栈管理结构体
typedef struct
{
    node *top; // 栈顶
    int size; // 节点数
}linkStack;

// 初始化链式栈
linkStack *init_linkStack(void)
{
    linkStack *ls = malloc(sizeof(linkStack));
    if(ls == NULL)
        return NULL;

    ls->top = NULL;
    ls->size = 0;

    return ls;
}

// 创建新节点
node *create_node(dataType data)
{
    node *pnew = malloc(sizeof(node));
    if(pnew == NULL)
        return NULL;
    pnew->data = data;
    pnew->next = NULL;
    return pnew;
}

// 入栈
bool push(linkStack *ls, dataType data)
{
    // 创建节点
    node *pnew = create_node(data);
    if(pnew == NULL)
        return false;

    // 头插
    pnew->next = ls->top;
    ls->top = pnew;
    ls->size++;

    return true;
}

// 判断栈是否为空
bool is_empty(linkStack *ls)
{
    return ls->size == 0;
}

// 获取栈顶节点元素
node *top(linkStack *ls)
{
    if(is_empty(ls))
        return NULL;
    return ls->top;
}

// 弹栈
node *pop(linkStack *ls)
{
    node *p = top(ls);
    if(p == NULL)
        return NULL;
    ls->top = p->next;
    p->next = NULL;
    ls->size--;
    return p;
}

int main(int argc, char const *argv[])
{
    // 初始化链式栈
    linkStack *ls = init_linkStack();
    if(ls == NULL)
    {
        printf("init linkstack failed\n");
        return -1;
    }

    // push(ls,1);
    // push(ls,2);
    // push(ls,3);

    // while(ls->size != 0)
    // {
    //     node *p = pop(ls);
    //     if(p == NULL)
    //     {
    //         printf("pop failed\n");
    //         return -1;
    //     }
    //     printf("%d\n",p->data);
    // }
    // printf("栈为空\n");

    int data;
    scanf("%d",&data);
    while(data>0)
    {
        
      
        push(ls,data%8);
        data/=8;
      
    }
    printf("0");
    while(1)
    {
        if(is_empty(ls))
            break;
        node *p=pop(ls);
        printf("%d",p->data);   
        
    }
    printf("\n");
    return 0;
}

4.队列(先进先出)

顺序循环队列

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int dataType;

typedef struct 
{
    dataType *data;
    int cap;
    int front;
    int rear;
}seqQueue;

//初始化队列
seqQueue *init_seqQueue(int size)
{
    seqQueue *sq=malloc(sizeof(seqQueue));
    if(sq==NULL)
        return NULL;
    sq->data=calloc(size,sizeof(dataType));
    sq->cap=size;
    sq->front=sq->rear=0;
    return sq;
}

//判断队列是否为满
bool  is_full(seqQueue *sq)
{
    return (sq->rear+1)%sq->cap==sq->front;
}

//队列为空
bool is_empty(seqQueue *sq)
{
    return sq->front==sq->rear;
}

//入队
bool enQuque(seqQueue *sq,dataType data)
{
    if(is_full(sq))
    {
        
        return false;
    }
        
    //尾入
    sq->data[sq->rear]=data;
    sq->rear=(sq->rear+1)%sq->cap;//尾巴的下标加一,下一次从此下标入队;
    return true;
}

//出队
bool outQueue(seqQueue *sq,dataType *data)
{
    if(is_empty(sq))
        return  false;
    *data=sq->data[sq->front];
    sq->front=(sq->front+1)%sq->cap;
    return true;

}
int main(int argc, char const *argv[])
{
    //初始化队列
    seqQueue *sq=init_seqQueue(5);
    if(sq==NULL)
    {
        printf("创建队列为空\n");
        return -1;
    }

    for (int i=0;i<4;i++)
    {
        enQuque(sq,i);
    }

    dataType data;
    while(1)
    {
        if(!outQueue(sq,&data))
        {
            printf("队列为空\n");
            break;
        }
        printf("%d\n",data);
    }
    return 0;
}

链式队列

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int dataType;

// 数据节点
struct node 
{
    dataType data;
    struct node *next;
}node;

// 管理结构体
typedef struct linkQueue
{
    struct node *fron; // 头节点
    struct node *rear; // 尾节点
    int size; // 节点数
}linkQueue;

// 初始化管理结构体
linkQueue *init_linkQueue()
{
    linkQueue *lq = malloc(sizeof(linkQueue));
    if(lq == NULL)
        return NULL;
    lq->fron = NULL;
    lq->rear = NULL;
    lq->size = 0;
    return lq;
}

// 队列为空
bool is_empty(linkQueue *lq)
{
    return lq->size == 0;
}

// 创建新节点
struct node *create_node(dataType data)
{
    struct node *pnew = malloc(sizeof(node));
    if(pnew == NULL)
        return NULL;

    pnew->data = data;
    pnew->next = NULL;

    return pnew;
}

// 入队
bool enQueue(linkQueue *lq, dataType data)
{
    // 创建新节点
    struct node *pnew = create_node(data);
    if(pnew == NULL)
        return false;

    // 从无到有
    if(is_empty(lq))
    {
        lq->fron = lq->rear = pnew;
    }
    else
    {
        lq->rear->next = pnew;
        lq->rear = pnew;
    }
    lq->size++;
    return true;
}

// 取队头元素,不出队
bool front(linkQueue *lq, dataType *data)
{
    if(is_empty(lq))
        return false;

    *data = lq->rear->data;
    return true;
}

// 出队
bool outQueue(linkQueue *lq, dataType *data)
{
    if(!front(lq,data))
    {
        return false;
    }

    // 将头节点剔除
    // 如果链表只有一个节点
    if(lq->size == 1)
    {
        free(lq->fron);
        lq->fron = NULL;
        lq->rear = NULL;
    }
    else
    {
        struct node *tmp = lq->fron;
        lq->fron = tmp->next;
        tmp->next = NULL;
        free(tmp);
    }
    lq->size--;
    return true;
}

//显示
void show(linkQueue *lq)
{
    struct node *pnew=lq->fron;
    while(pnew!=NULL)
    {
        printf("%d\t",pnew->data);
        pnew=pnew->next;
    }
    printf("\n");  

}

int main(int argc, char const *argv[])
{
    //初始化管理结构体
    linkQueue *lq=init_linkQueue();
    if (lq==NULL)
    {
        printf("init queue failed\n");
        return -1;
    }

    while(1)
    {
        dataType data=-1;
        if(scanf("%d",&data)==1)
        {
            if(!enQueue(lq,data))
            {
                printf("队列满\n");
                break;
            }
        }
        else
        {
            while(getchar() != '\n');
            dataType data = -1;
            if(!outQueue(lq,&data))
            {
                printf("队列空\n");
                break;
            }
        }
        show(lq);
    }

    return 0;
}

lq->size == 1)
{
free(lq->fron);
lq->fron = NULL;
lq->rear = NULL;
}
else
{
struct node *tmp = lq->fron;
lq->fron = tmp->next;
tmp->next = NULL;
free(tmp);
}
lq->size–;
return true;
}

//显示
void show(linkQueue *lq)
{
struct node *pnew=lq->fron;
while(pnew!=NULL)
{
printf(“%d\t”,pnew->data);
pnew=pnew->next;
}
printf(“\n”);

}

int main(int argc, char const *argv[])
{
//初始化管理结构体
linkQueue *lq=init_linkQueue();
if (lq==NULL)
{
printf(“init queue failed\n”);
return -1;
}

while(1)
{
    dataType data=-1;
    if(scanf("%d",&data)==1)
    {
        if(!enQueue(lq,data))
        {
            printf("队列满\n");
            break;
        }
    }
    else
    {
        while(getchar() != '\n');
        dataType data = -1;
        if(!outQueue(lq,&data))
        {
            printf("队列空\n");
            break;
        }
    }
    show(lq);
}

return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值