3/8/24单链表真题、栈初始化、出入栈、循环队列及其实现

目录

 单链表真题2019-41​编辑

OJ单链表查找、增加、删除

栈的原理解析

栈初始化、入栈、出栈

队列

循环队列

循环队列实现

栈需要定义位置元素指向栈顶,通过栈顶后进先出。

队列需要定义队首和对位元素,注意出栈入栈后队首和队尾的指向不要超过最大长度。

 单链表真题2019-41

 解题设计:

  1. 如何找到链表的中间结点、
  2. 后一半链表设置为L2,如何让L2原地逆置。
  3. 将L与L2链表合并,合并时轮流放入一个结点。

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

typedef int ElemType;
typedef struct node {
    ElemType data;
    struct node *next;
} NODE;

void LinkTail(NODE *&L) {
    L = (NODE *) malloc(sizeof(NODE));
    L->next = NULL;
    ElemType elem;
    NODE *r = L, *p;
    scanf("%d", &elem);
    while (elem != 9999) {
        p = (NODE *) malloc(sizeof(NODE));
        p->data = elem;
        r->next = p;
        r = p;
        scanf("%d", &elem);
    }
    r->next = NULL;
}

//找到中间节点,并设置好L2
NODE *FindMiddle(NODE *L, NODE *&L2) {
    L2 = (NODE *) malloc(sizeof(NODE));
    NODE *pcur, *ppre;//双指针法。双指针遍历是考研常考点
    pcur = ppre = L->next;
    while (pcur) {
        pcur = pcur->next;
        if (NULL == pcur || NULL == pcur->next) break;
        pcur = pcur->next;
        ppre = ppre->next;
    }
    L2->next = ppre->next;
    ppre->next = NULL;
}

void Reverse(NODE *L2) {
    NODE *r, *s, *t;
    r = L2->next;
    if (NULL == r || NULL == r->next)return;//链表无结点或只有一个结点直接返回
    s = r->next;
    t = s->next;
    while (NULL != t) {//逆置
        s->next = r;
        r = s;
        s = t;
        t = t->next;
    }
    s->next = r;
    L2->next->next = NULL;//L2头结点next第一个结点next=NULL
    L2->next = s;
}

void Merge(NODE *L, NODE *L2) {
    NODE *mid, *p, *p2;
    mid = L->next;//mid始终指向新列表的表尾
    p = mid->next, p2 = L2->next;
    if (NULL == p2)return;
    while (NULL != p) {
        mid->next = p2;
        mid = mid->next;
        p2 = p2->next;
        mid->next = p;
        mid = mid->next;
        p = p->next;
    }
    if (NULL != p2){
        mid->next = p2;
        mid = mid->next;
    }
    mid->next=NULL;
}

void PrintLink(NODE *L) {
    while (L->next != NULL) {
        printf("%3d", L->next->data);
        L = L->next;
    }
    printf("\n");
}


int main() {
    NODE *L;
    LinkTail(L);
    //寻找中间结点
    NODE *L2 = NULL;
    FindMiddle(L, L2);
    Reverse(L2);
    Merge(L, L2);
    PrintLink(L);
    return 0;
}
FindMiddle、Reverse、Merge函数的循环次数均为n/2,总运行次数是1.5n,因此整个程序的时间复杂度为O(n)。

栈 

OJ单链表查找、增加、删除

输入3 4 5 6 7 9999一串整数,9999代表结束,通过尾插法新建链表,查找第二个位置的值并输出,在2个位置插入99,输出为  3 99  4  5  6  7,删除第4个位置的值,打印输出为  3 99  4  6  7。

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

typedef struct Node {
    int data;
    struct Node *next;
} Node, *NodeLink;

void TailLink(NodeLink &L) {
    L = (NodeLink) malloc(sizeof(Node));
    L->next = NULL;
    NodeLink pcur, pmid;
    pcur = L;
    int x;
    scanf("%d", &x);
    while (9999 != x) {
        pmid = (NodeLink) malloc(sizeof(Node));
        pmid->data = x;
        pcur->next = pmid;
        pcur = pmid;
        scanf("%d", &x);
    }
    pcur->next = NULL;
}

NodeLink FindNode(NodeLink L, int i) {
    if (i < 0) return NULL;
    for (int j = 1; j <= i && NULL != L; j++) {
        L = L->next;
    }
    return L;
}

bool InsertNode(NodeLink L, int i, int val) {
    NodeLink pper = FindNode(L, i - 1);
    if (NULL == pper) return false;
    NodeLink p = (NodeLink) malloc(sizeof(Node));
    p->data = val;
    p->next = pper->next;
    pper->next = p;
    return true;
}

bool DeleteNode(NodeLink L) {
    NodeLink pper = FindNode(L, 3);
    if (NULL == pper || NULL == pper->next)return false;
    NodeLink p = pper->next;
    pper->next = p->next;
    free(p);
    p = NULL;
    return true;
}


void PrintLink(NodeLink L) {
    L = L->next;
    while (NULL != L) {
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}

int main() {
    NodeLink L;
    TailLink(L);
    NodeLink ptwo = FindNode(L, 2);
    if (ptwo)printf("%d\n", ptwo->data);
    InsertNode(L, 2, 99);
    PrintLink(L);
    DeleteNode(L);
    PrintLink(L);
    return 0;
}

栈的原理解析

栈中元素先进后出,最先入栈为栈底,最后入栈为栈顶。

 链栈了解即可。

 

出栈并不会改变元素,而是改变top的栈顶指向 。

栈初始化、入栈、出栈

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

#define MaxSize 50
typedef int ElemType;
typedef struct {
    ElemType data[MaxSize];//数组
    int top;//始终指向栈顶位置的变量
} SqStack;

void InitStack(SqStack &S) {
    S.top = -1;//初始化栈,即S.top=-1栈为空
}

bool StackEmpty(SqStack S) {
    if (-1 == S.top) return true;
    else return false;
}

//入栈
bool Push(SqStack &S, ElemType x) {
    //判断栈是否满了
    if (MaxSize - 1 == S.top) {
        return false;
    }
    S.data[++S.top] = x;
    return true;
}

//获取栈顶元素
bool GetTop(SqStack S, ElemType &m) {
    if (StackEmpty(S))return false;
    m = S.data[S.top];
    return true;
}

//弹栈
bool Pop(SqStack &S,ElemType &m){
    if (StackEmpty(S))return false;
    m=S.data[S.top--];//出栈
    return true;
}

int main() {
    SqStack S;
    InitStack(S);
    bool flag;
    flag = StackEmpty(S);
    if (flag) printf("Stack is empty\n");
    Push(S, 3);
    Push(S, 4);
    Push(S, 5);
    ElemType m;
    flag = GetTop(S, m);
    if (flag) printf("Get top %d\n", m);
    flag = Pop(S,m);
    if(flag) printf("pop element %d\n",m);
    return 0;
}

队列

简称队,是一种操作受限的线性表。只允许在对首(Front)进行插入(入队或进队),队尾(Rear)进行删除(出队或离队)。FIFO(first in first out)

循环队列

存储个数为MaxSize-1个,(Q.rear+1)%MaxSize==Q.front以判断循环队列满队。

循环队列实现

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

#define MaxSize 5
typedef int ElemType;
typedef struct {
    ElemType data[MaxSize];
    int front, rear;
} SqQueue;

void InitQueue(SqQueue &Q) {
    Q.front = Q.rear = 0;//初始化循环队列,让队首和队尾都指向0
}

bool IsEmpty(SqQueue Q) {
    return (Q.rear == Q.front);
}

//入队
bool EnQueue(SqQueue &Q, ElemType x) {
    if (Q.front == (Q.rear + 1) % MaxSize)return false;//判断循环队列是否满队
    Q.data[Q.rear] = x;//放入元素
    Q.rear = (Q.rear + 1) % MaxSize;//rear后移,同时让rear在MaxSize范围内
    return true;

}

//出队
bool DeQueue(SqQueue &Q, ElemType &x) {
    if (IsEmpty(Q)) return false;//空队列无法出队
    x = Q.data[Q.front];//出队
    Q.front = (Q.front + 1) % MaxSize;
    return true;
}

int main() {
    SqQueue Q;
    InitQueue(Q);
    bool ret;
    ret = IsEmpty(Q);
    if (ret) printf("SqQueue is empty\n");
    else printf("SqQueue is not empty\n");
    EnQueue(Q, 3);
    EnQueue(Q, 4);
    EnQueue(Q, 5);
    ret = EnQueue(Q, 6);
    ret = EnQueue(Q, 7);
    if (ret)printf("EnQueue Successfully\n");
    else printf("EnQueue failed\n");
    ElemType elem;//存储出队元素
    ret = DeQueue(Q, elem);
    if (ret)printf("DeQueue %d Successfully\n", elem);
    else printf("DeQueue failed\n");
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值