数据结构——栈与队列

article/2025/11/7 13:32:34

目录

一、栈

1.栈的定义

 2.栈的分类与基本操作

1. 顺序栈

2.链栈

3.栈与递归的实现

1.递归的简单描述

2.递归过程及与栈的关联

3.递归过程示意图

二.队列

1.队列的定义

 2.队列的分类与基本操作

1.顺序队列

2.链队列

3.循环队列

1.假溢出

 2.循环队列

3.循环队列相关操作实现:


栈和队列是两种重要的线性结构。从数据结构的角度来看,栈与队列均属于线性表,其特殊性在于栈与队列的基本操作为线性表基本操作的子集,栈与队列为操作受限的线性表,故,栈与队列可称为限定性的数据结构,

一、栈

1.栈的定义

栈,是限定仅在表尾进行插入与删除操作的线性表。对于栈来说,表尾端具有特殊的含义,称为栈顶,相应地将表头段成为栈底。不含元素的空表称为空栈。

栈的修改是按照后进先出的原则进行的,因此将栈成为后进先出的线性表。

栈的示意图:

模拟实现出栈与入栈操作:(以顺序栈为例)

 2.栈的分类与基本操作

栈有两种存储表示方式:顺序存储方式与链式存储方式

1. 顺序栈

栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置(位置应与数据在顺序表中的下标区分理解)。

一种定义顺序栈的常用方法:先为栈分配一个初始容量,在实际应用过程中,当栈的存储空间不够时再逐段扩容。

以下为顺序栈的相关基本操作:

方法1:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>#define Stack_Init_Size 10
#define Stack_Add_Size 5//定义顺序栈的结构体
typedef int ElemType;
typedef struct Stack
{ElemType* base;	//定义栈底指针ElemType* top;	//定义栈顶指针int capacity;	//指明当前栈的容量
}Stack;//栈的初始化操作
void StackInit(Stack* ps)
{ps->base = (ElemType*)malloc(sizeof(ElemType) * Stack_Init_Size);if (NULL == ps->base) //空间申请失败处理{printf("空间申请失败\n");exit(0);}ps->top = ps->base;ps->capacity = Stack_Init_Size;
}
//栈的判空操作
bool StackIsEmpty(Stack* ps)
{return ps->base == ps->top ? true : false;
}
//当前栈内元素数量
int StackNum(Stack* ps)
{return ps->top - ps->base;
}
//获取栈顶元素
void GetTop(Stack* ps, ElemType* e)
{assert(ps);if (ps->base == ps->top){printf("当前栈中无元素\n");return;}*e = *(ps->top - 1);
}
//出栈
void StackPop(Stack* ps, ElemType* e)
{assert(ps);if (ps->base == ps->top){printf("当前栈中无元素\n");exit(0);}*e = *(--ps->top);
}
//检查栈是否需要扩容
void StackCheckCapacity(Stack* ps)
{assert(ps);if (ps->top - ps->base >= ps->capacity){ps->base = (ElemType*)realloc(ps->base, sizeof(ElemType) * (ps->capacity + Stack_Add_Size));if (NULL == ps->base){printf("空间申请失败\n");exit(0);}ps->top = ps->base + ps->capacity;ps->capacity += Stack_Add_Size;}
}
//入栈
void StackPush(Stack* ps, ElemType e)
{assert(ps);StackCheckCapacity(ps);*(ps->top++) = e;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{assert(ps);if (ps->base){free(ps->base);ps->base = NULL;ps->capacity = 0;}
}

方法2:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>#define Stack_Init_Size 10
#define Stack_Add_Size 5typedef int ElemType;
typedef struct Stack
{ElemType* data;int top;		// 栈顶int capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps)
{ps->data = (ElemType*)malloc(sizeof(ElemType) * Stack_Init_Size);if (NULL == ps->data){printf("空间申请失败\n");exit(0);}ps->capacity = Stack_Init_Size;ps->top = 0;
}
//扩容判断
void CapacityCheck(Stack* ps)
{assert(ps);if (ps->top >= ps->capacity){ps->data = (ElemType*)realloc(sizeof(ElemType) * (ps->capacity + Stack_Add_Size));if (NULL == ps->data){printf("空间申请失败\n");exit(0);}ps->capacity += Stack_Add_Size;}
}
// 入栈 
void StackPush(Stack* ps, ElemType data)
{assert(ps);CapacityCheck(ps);ps->data[ps->top++] = data;
}
// 出栈 
void StackPop(Stack* ps)
{assert(ps);if (ps->top == 0){printf("当前栈中无元素\n");return;}ps->top--;
}
// 获取栈顶元素 
ElemType StackTop(Stack* ps)
{assert(ps);if (ps->top == 0){printf("当前栈中无元素\n");return;}return ps->data[ps->top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{return ps->top == 0 ? 1 : 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{assert(ps);if (ps->data){free(ps->data);ps->data = NULL;ps->capacity = 0;ps->top = 0;}
}

2.链栈

栈的链式存储结构是利用若干结点存储数据元素并组成链表,同时附设top和base指针指示栈顶与栈底的位置。

链栈的逻辑结构示意图:

 以下为链栈的相关基本操作:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int ElemType;
typedef struct StackNode
{ElemType data;struct StackNode* next;
}StackNode;
typedef struct Stack
{StackNode* base;StackNode* top;
}Stack;//创建结点
StackNode* BuyNewNode()
{StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));if (NULL == newNode){printf("空间申请失败\n");exit(0);}newNode->next = NULL;return newNode;
}
// 初始化栈 
void StackInit(Stack* ps)
{ps->base = BuyNewNode();ps->top = ps->base;
}
// 入栈 
void StackPush(Stack* ps, ElemType data)
{assert(ps);StackNode* newNode = BuyNewNode();newNode->data = data;newNode->next = ps->top->next;ps->top = BuyNewNode();ps->top->next = newNode;
}
// 出栈 
void StackPop(Stack* ps)
{assert(ps);if (ps->top == ps->base){printf("现在栈中无元素\n");return;}StackNode* temp = ps->top->next;ps->top->next = temp->next;free(temp);temp = NULL;
}
// 获取栈顶元素 
ElemType StackTop(Stack* ps)
{return ps->top->next->data;
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{int count = 0;StackNode* temp = ps->top->next;while (temp != NULL){count++;temp = temp->next;}return count;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{return ps->top == ps->base ? 1 : 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{assert(ps);while (ps->top){StackNode* temp = ps->top;ps->top = temp->next;free(temp);}free(ps->base);ps->base = NULL;ps->top = NULL;
}

3.栈与递归的实现

1.递归的简单描述

栈的一个重要应用是在程序设计语言中实现递归。一个直接调用自己或通过一系列的调用语言间接地调用自己地函数,称之为递归函数。

递归是在程序设计中一个强有力地工具。第一,存在许多数学函数是递归定义的,如阶乘函数,斐波那契数列等;第二,有的数据结构,如二叉树,广义表等,他们地结构本身固有递归特性,故他们地操作可递归地描述;第三,某类型的问题,虽然问题本身并没有明显的递归结构,但采用递归求解比迭代求解更方便,如汉诺塔问题。

2.递归过程及与栈的关联

当在一个函数运行期间调用另一个函数时,在运行被调函数之前,系统需要完成三件事:

1.将所有的实参,返回地址等信息传递给被调用函数保存;

2.为被调用函数的局部变量分配存储空间;

3.将控制转移到被调函数的入口。

而从被调函数返回调用函数之前,系统同样完成三项工作:

1.保存被调函数的计算结果;

2.释放被调用函数的数据区;

3.依照被调用函数保存的返回地址将控制转移到调用函数。

多个函数嵌套调用时,按照“后调用先返回”的原则,调用与被调用函数之间的信息传递与控制转移都需要通过栈来实现。

系统将整个程序运行过程中所需的数据空间安排在一个栈中,即“递归工作栈”,每当调用一个函数时,就在栈顶给他分配一个存储区,将当前层递归所需信息构成一个“工作记录”,其中包含调用函数的所有实参,局部变量以及返回地址,将该条工作记录压入栈顶;每当一个函数退出时,就释放他的存储区,从栈顶弹出一个工作记录。当前运行的程序的数据区必须在栈顶。

3.递归过程示意图

为了更加具体地描述递归过程及递归过程中栈地应用,方便读者理解,这里给出一个具体递归函数,通过具体案例描述递归过程:

int Fib(int n)
{if (n == 0){return 1;}return Fib(n - 1);
}

递归实现过程:

上述递归函数的函数调用栈示意图:

二.队列

1.队列的定义

队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素。在队列中允许插入的一端叫做队尾,允许删除的一端则称为队头。

队列的逻辑示意图:

 队列的出队、入队操作示意图:(此处只做逻辑解释,不涉及具体存储结构)

 2.队列的分类与基本操作

和线性表类似,队列根据存储结构的不同可以分为两类:顺序队列与链式队列。

1.顺序队列

由于顺序队列采用一组地址空间连续的存储空间依次存放队列中的数据元素,在多次出队、入队操作中可能会造成假溢出的现象,使得存储空间利用率不高,为解决假溢出的现象,大佬们引入了循环队列的概念,由于假溢出现象的存在,使得单一线性存储结构不适用于队列,所以此处不多阐述顺序队,详情在下文循环队列中解决。

2.链队列

用链表表示的队列称为链队列。一个链队列需要两个分别指示队头与队尾的指针才能唯一确定。

给出链队列的逻辑示意图:

 以下为链队列的相关基本操作:

1.方法一:实现带有头结点的链队列

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义队列的结构体
typedef int ElemType;
typedef struct QueueNode
{ElemType data;struct QueueNode* next;
}QueueNode;
typedef struct Queue
{QueueNode* front;QueueNode* rear;
}Queue;//创建队列的结点
QueueNode* BuyNewNode(ElemType e)
{QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));if (NULL == newNode){printf("空间申请失败\n");system("pause");return;}newNode->next = NULL;newNode->data = e;return newNode;
}
// 初始化队列 
void QueueInit(Queue* q)
{//定义具有头结点的队列q->front = (QueueNode*)malloc(sizeof(QueueNode));if (NULL == q->front){printf("空间申请失败\n");system("pause");return;}q->front->next = NULL;q->rear = q->front;
}
// 队尾入队列 
void QueuePush(Queue* q, ElemType data)
{assert(q);QueueNode* newNode = BuyNewNode(data);q->rear->next = newNode;q->rear = newNode;
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);if (q->rear == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}else if (q->front->next == q->rear) //当前队列仅有一个元素{QueueNode* newNode = q->rear;q->front->next = NULL;q->rear = q->front;free(newNode);newNode = NULL;}else //当前队列有多个元素{QueueNode* newNode = q->front->next;q->front->next = newNode->next;free(newNode);newNode = NULL;}
}
// 获取队列头部元素 
ElemType QueueFront(Queue* q)
{assert(q);if (q->rear == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}return q->front->next->data;
}
// 获取队列队尾元素 
ElemType QueueBack(Queue* q)
{assert(q);if (q->rear == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}return q->rear->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);if (q->rear == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}int count = 0;QueueNode* cur = q->front->next;while (cur){count++;cur = cur->next;}return count;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{return q->front == q->rear;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);if (QueueEmpty(q)){free(q->front);q->front = NULL;q->rear = NULL;}else{QueueNode* cur = q->front->next;while (cur){QueueNode* temp = cur->next;free(cur);cur = temp;}free(q->front);q->front = NULL;q->rear = NULL;}
}

2.方法二:实现不带头结点的链队列

 #include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义队列的结构体
typedef int ElemType;
typedef struct QueueNode
{ElemType data;struct QueueNode* next;
}QueueNode;
typedef struct Queue
{QueueNode* front;QueueNode* rear;
}Queue;//创建队列的结点
QueueNode* BuyNewNode(ElemType e)
{QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));if (NULL == newNode){printf("空间申请失败\n");system("pause");return;}newNode->next = NULL;newNode->data = e;return newNode;
}
// 初始化队列 
void QueueInit(Queue* q)
{q->front = NULL;q->rear = q->front;
}
// 队尾入队列 
void QueuePush(Queue* q, ElemType data)
{assert(q);QueueNode* newNode = BuyNewNode(data);if (q->front == NULL) //此时队列为空{q->front = q->rear = newNode;}{q->rear->next = newNode;q->rear = newNode;}
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);if (q->front == NULL) //当前队列无元素{printf("当前队列中为空\n");return;}else if (q->front == q->rear) //当前队列仅有一个元素{QueueNode* newNode = q->rear;q->front = NULL;q->rear = q->front;free(newNode);newNode = NULL;}else //当前队列有多个元素{QueueNode* newNode = q->front;q->front = newNode->next;free(newNode);newNode = NULL;}
}
// 获取队列头部元素 
ElemType QueueFront(Queue* q)
{assert(q);if (NULL == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}return q->front->data;
}
// 获取队列队尾元素 
ElemType QueueBack(Queue* q)
{assert(q);if (NULL == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}return q->rear->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);if (NULL == q->front) //当前队列无元素{printf("当前队列中为空\n");return;}int count = 0;QueueNode* cur = q->front;while (cur){count++;cur = cur->next;}return count;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{return q->front == NULL;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);if (QueueEmpty(q)){free(q->front);q->front = NULL;q->rear = NULL;}else{QueueNode* cur = q->front;while (cur){QueueNode* temp = cur->next;free(cur);cur = temp;}q->front = NULL;q->rear = NULL;}
}

3.循环队列

1.假溢出

队列由于受到“队尾入队,队头出队”这种操作的影响,会在某些状态下不可在插入新的队尾元素,否则会出现溢出现象,即因数组越界而导致程序的非法操作错误。但事实上,此时队列的实际可用空间并未占满,所以这种现象称为假溢出。

示意图:

 2.循环队列

为解决“假溢出”问题,大佬们提出了循环队列,即将顺序队列在逻辑上抽象为一个环状的空间,称为循环队列。

 在循环队列中,头、尾指针以及队列元素之间的关系不变,头、尾指针“依环状增1”的操作可通过“模”运算来实现,通过取模,头、尾指针可以在顺序空间内以头尾衔接的方式“循环”移动。

循环队列的判空、判满方法通常有以下两种处理方法:

(1)少使用一个元素空间,即队列大小为m时,有m-1个元素即认为队满,判空条件不变;

        队空条件:front == rear

        队满条件:(rear+1)%size = front

(2) 另设一个标志位来区别是“空”还是“满”。

3.循环队列相关操作实现:

1.方法 1 :少使用一个存储空间

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>#define Queue_Init_Size 10//设计循环队列结构体
typedef int ElemType;
typedef struct Queue
{ElemType* data;int front; //队头元素的下标int rear;  //队尾元素的下标
}Queue;// 初始化队列 
void QueueInit(Queue* q)
{q->data = (ElemType*)malloc(sizeof(ElemType) * Queue_Init_Size);if (NULL == q->data){printf("空间申请失败\n");system("pause");exit(0);}q->front = 0;q->rear = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, ElemType data)
{assert(q);if ((q->rear + 1) % Queue_Init_Size == q->front){printf("当前队列已满\n");return;}q->data[q->rear] = data;q->rear = (q->rear + 1) % Queue_Init_Size;
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);if (QueueEmpty(q)){printf("当前队列为空\n");return;}q->front = (q->front + 1) % Queue_Init_Size;
}
// 获取队列头部元素 
ElemType QueueFront(Queue* q)
{if (!QueueEmpty(q)){return q->data[q->front];}
}
// 获取队列队尾元素 
ElemType QueueBack(Queue* q)
{if (!QueueEmpty(q)){return q->data[(q->rear - 1 + Queue_Init_Size) % Queue_Init_Size];}
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{return (q->rear - q->front + Queue_Init_Size) % Queue_Init_Size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{return q->front == q->rear;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);if (q->data != NULL){free(q->data);q->data = NULL;}q->front = 0;q->rear = 0;
}

2.方法 2:另设一个标志位

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>#define Max_Size 10//设计循环队列结构体
typedef int ElemType;
typedef struct QArray
{ElemType data;int flag;//标志位 0-表示为非空 1-表示为空
}QArray;
typedef struct Queue
{QArray* task;int front;int rear;
}Queue;// 初始化队列 
void QueueInit(Queue* q)
{q->task = (QArray*)malloc(sizeof(QArray) * Max_Size);if (NULL == q->task){printf("空间申请失败\n");exit(0);}for (int i = 0; i < Max_Size; ++i){q->task[i].flag = 1;}q->front = 0;q->rear = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, ElemType data)
{assert(q);if (q->rear == q->front && q->task[q->rear].flag == 0){printf("当前队列空间已满\n");return;}q->task[q->rear].data = data;q->task[q->rear].flag = 0;q->rear = (q->rear + 1) % Max_Size;
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);if (QueueEmpty(q)){printf("当前队列为空\n");return;}q->task[q->front].flag = 1;q->front = (q->front + 1) % Max_Size;
}
// 获取队列头部元素 
ElemType QueueFront(Queue* q)
{assert(q);if (!QueueEmpty(q)){return q->task[q->front].data;}
}
// 获取队列队尾元素 
ElemType QueueBack(Queue* q)
{assert(q);if (!QueueEmpty(q)){return q->task[(q->rear - 1 + Max_Size) % Max_Size].data;}
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{return q->rear == q->front && q->task[q->rear].flag == 1;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);if (QueueEmpty(q)){return 0;}else if (q->rear == q->front && q->task[q->rear].flag == 0){return Max_Size;}else{return (q->rear - q->front + Max_Size) % Max_Size;}
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);if (NULL != q->task){free(q->task);q->task = NULL;}q->front = 0;q->rear = 0;
}

http://chatgpt.dhexx.cn/article/pwXcnXA1.shtml

相关文章

栈与队列详解

目录 申明1. 栈的定义1.1 栈的定义1.2 进栈出栈变化形式 2. 栈的抽象数据类型3. 栈的顺序存储结构及实现3.1 栈的顺序存储结构3.2 栈的顺序存储结构——进栈操作3.3 栈的顺序存储结构——出栈操作 4. 两栈共享空间5. 栈的链式存储结构及实现5.1 栈的链式存储结构5.2 栈的链式存…

栈与队列(超详细)

目录 一、栈&#xff08;Stack&#xff09;1、什么是栈&#xff1f;2、栈的常见方法3、自己实现一个栈&#xff08;底层用一个数组实现&#xff09; 二、队列&#xff08;Queue&#xff09;1、什么是队列&#xff1f;2、队列的常见方法3、队列的实现&#xff08;单链表实现&…

C语言---栈和队列

严格来说,栈和队列都属于线性表 "一对一" 栈:"先进后出" 队列: "先进先出" 栈 栈只能从一端存取,另一端是封闭的 在栈中,不论是存还是取,都必须遵循"先进后出"的原则 >栈是一种只能从表的一端存取数据,且遵循"先进后出…

数据结构与算法——栈和队列

&#x1f60a;数据结构与算法——栈和队列 &#x1f680;前言&#x1f680;栈&#xff08;satck&#xff09;&#x1f6a2;栈的定义&#x1f6a2;共享栈&#xff08;节省空间&#xff09;&#x1f6a2;栈的表示和实现&#xff08;顺序栈&#xff09;&#x1f47b;顺序栈的定义&…

数据结构:栈和队列(Stack Queue)【详解】

友情链接&#xff1a;数据结构专栏 目录 栈和队列【知识框架】 栈一、栈的基本概念1、栈的定义2、栈的常见基本操作 二、栈的顺序存储结构1、栈的顺序存储2、顺序栈的基本算法&#xff08;1&#xff09;初始化&#xff08;2&#xff09;判栈空&#xff08;3&#xff09;进栈&a…

web 移动端开发基础

web 移动端开发基础 文章目录 web 移动端开发基础了解视口相关内容meta 视口标签掌握二倍图用法物理像素 & 物理像素比多倍图二倍精灵图做法 了解移动端常见选择方案掌握移动端常见问题解决方案移动端常见的布局方式流式布局&#xff08;百分比布局&#xff09;flex 布局 -…

Web移动端

1.PC端和移动端的区别: PC端:屏幕大 用网页固定版心,要考虑浏览器兼容问题,(布局:浮动&#xff0b;定位&#xff0b;标准流) 移动端: 手机屏幕小&#xff0c;网页宽度多数为100%&#xff0c;是适配手机屏幕宽度 移动端则基本不需要考虑兼容性问题&#xff0c;放心大胆使用CS…

移动端网页开发基础

文章目录 前言一、浏览器1.pc端常见浏览器2.移动端常见浏览器 二、视口1.布局视口layout viewport2.视觉视口visual viewport3.理想视口ideal viewport 三、二倍图1.物理像素和物理像素比2.二倍图用法 四、移动端开发选择1.单独制作移动端页面2.响应式兼容pc移动端3.移动端常见…

20.【移动端Web开发之响应式布局】

文章目录 【移动端Web开发之响应式布局】前端小抄(20)一、响应式开发1.1 响应式开发原理1.2 响应式布局容器 二、Bootstrap前端开发框架2.1 Bootstrap简介2.2 Bootstrap使用2.3 布局容器 三、Bootstrap栅格系统3.1 栅格系统简介3.2 栅格选项参数3.3 列嵌套3.4 列偏移3.5 列排序…

H5移动web开发

目录 1、H5 的新特性有哪些&#xff1f;C3 的新特性有哪些&#xff1f; 2、如何使一个盒子水平垂直居中&#xff1f; 方法一&#xff1a;利用定位&#xff08;常用方法,推荐&#xff09; 方法二&#xff1a;利用 margin:auto 方法三&#xff1a;利用 display:table-cell 方法四…

手摸手带你学移动端WEB开发

HTML常用标签总结手摸手带你学CSSHTML5与CSS3知识点总结 好好学习&#xff0c;天天向上 本文已收录至我的Github仓库DayDayUP&#xff1a;github.com/RobodLee/DayDayUP&#xff0c;欢迎Star ⭐⭐⭐⭐⭐转载请注明出处&#xff01;⭐⭐⭐⭐⭐ 链接&#xff1a;https://blog.c…

移动端网页开发(一)

一、项目代码初始化 1.打开index.html将<meta></meta>标签补充完整 <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0&#xff0c;minimum-scale1.0,maximum-…

web移动开发

web移动开发 手机内置浏览器&#xff1a; Android&#xff1a;Andriod BrowserIOS&#xff1a;Mobile SafariBlackBerry&#xff1a;WebkitSymbian S60&#xff1a; Web Browser for S60 其浏览器的核心都是基于Webkit 智能手机Web浏览器的特点: 有限的屏幕尺寸触屏、缩放硬…

移动端页面开发

移动端页面开发需要掌握的…… 移动端开发指的是&#xff1a;需要适配移动设备的网页开发移动开发与pc端开发没有本质的区别&#xff0c;使用的也还是HTML/CSS/JS的技术 一、移动端与pc端开发的区别在于&#xff1a; 1.浏览器不同 手机浏览器是webkit的天下&#xff0c;就目…

从零开始学习移动端Web开发

背景 近年来&#xff0c;随着智能手机的普及&#xff0c;移动端开发受到了异常的关注。从传统的安卓、IOS原生手机系统应用开发&#xff0c;转向了移动端Web开发或者是混合开发&#xff0c;既然有需求&#xff0c;那就让我们一起来学习移动端Web开发吧。本文旨在让读者以最快的…

移动端网站开发

受限于流量太少&#xff0c;以前的手机网站无法做成像现在一样的效果&#xff0c;只能通过超链接的形式实现简单的网页 随着3G&#xff0c;4G&#xff0c;5G的商用&#xff0c;我们的流量越来越多&#xff0c;网速越来越快。越来越多的应用开始去开发网页版。 移动端仿真 未来…

移动端开发

2022.3.5 学习笔记 目录 四、移动端开发方案 五、 移动端技术解决方案 六、移动端常见布局 移动端开发之流式布局&#xff1a; 一、基础 二、制作京东移动端首页案例 四、移动端开发方案 ①单独制作移动端页面 &#xff08;主流&#xff09; 京东商城手机版 淘宝触屏版…

web前端开发之移动端基础

web前端开发之移动端基础 一、物理像素(px) 定义&#xff1a;虚拟像素&#xff0c;可以理解为“直觉”像素&#xff0c;CSS和JS使用的抽象单位&#xff0c;浏览器内的一切长度都是以CSS像素为单位的&#xff0c;CSS像素的单位是px。 1.2 像素到底是什么 像素&#xff08;px…

前端移动端web开发(一)

一、前端开发 1.前端开发分类&#xff1a; PC端开发&#xff1a;页面主要运行在PC端浏览器中 移动端开发&#xff1a;页面主要运行在手机上 移动web开发 在移动端表现良好的页面&#xff0c;如新浪网 混合式开发&#xff08;Hybrid App&#xff09; 也叫“套壳开发”&#xf…

移动端Web开发 基础知识

文章目录 移动端Web开发移动端基础浏览器视口样式编写分辨率和设备像素比二倍图SVG矢量图 移动端Web开发 移动Web开发的两种主流方案&#xff0c;一种是单独制作移动端页面&#xff0c;另一种是制作响应式页面 移动端页面&#xff1a; 单独制作移动端页面的优势和劣势&#…