栈的原理以及实现(基于数组)

栈的定义:

限制仅在表的一端进行插入和删除运算的线性表。

可以实现“先进后出(或者叫后进先出)”的存储结构。

栈顶(Top): 允许操作的一端。

栈底(Bottom): 不允许操作的一端。

特点:后进先出。

举例:物流装车,先装车的后出来,后装车的先出来。

图片加载中

栈的结构:

空栈:栈顶和栈顶都指向一个无用的头结点


存有结点的栈:栈顶指针指向栈顶结点,栈底指针指向头结点


栈的三种实现方案:静态数组、动态分配的数组、动态分配的链式结构。

静态数组:长度固定,在编译时确定。优点:结构简单,实现方便。缺点:不够灵活、适用于知道明确长度的场合。

动态数组:长度可在运行的时才确定,并且可以更改原来数组的长度。优点:灵活。缺点:会因此增加程序的复杂性。

链式结构:无长度上限。需要的时候再申请分配内存空间。优点:最灵活。缺点:链式结构的链接字段需要消耗一定内存;在链式结构中访问特定元素效率不如数组。

栈的三种实现

首先确定一个栈接口的头文件,里面包含了各个实现方案下的函数原型,放在一起是为了实现程序的模块化以及便于修改。然后再分别介绍各个方案的具体实现方法。


静态数组实现栈:

/* 
**  
** 静态数组实现堆栈程序,数组长度由#define确定 
*/  
  
#include <stack.h>
#include <stdio.h>
#include <assert.h>

#define STACK_SIZE 100 /*栈最大容纳元素数量*/

typedef struct Stack{
	SElemType data[STACK_SIZE];  /*栈中的数组*/
	int top; /*指向栈顶元素的指针*/
}SeqStack;

/*init stack*/
void InitStack(SeqStack *S)
{
	S->top = 0;
}
/*判断栈是否为空*/
int StackEmpty(SeqStack *S)
{
	if(S->top == 0)
		return 1;
	else
		return 0;
}
/*取栈顶元素*/
int GetTop(SeqStack S, SElemType *e)
{
	if(S->top <= 0){
		printf("当前栈已空\n");
		return 0;
	}
	*e = S.stack[S.top - 1];
	return 1;
}
/*将元素e入栈*/
int push(SeqStack *S, SElemType e)
{
	if(S->top >= StackSize){
		printf("栈满\n");
		return 0;	
	}
	S->stack[S->top] = e;
	S->top ++;
	return 1;
}
/*将栈顶元素出栈,并赋值给e*/
int PopStack(SeqStack *S, SElemType *e)
{
	if(S->top == 0){
		printf("空栈");	
		return 0;
	}
	S->top --; 
	*e = S->stack[S->top];
	return 1;
}
/*栈的长度*/
int StackLength(SeqStack S){
     return S.top;//存储着数据的部分是0到top-1,入栈时,如果栈未满,则在top处存入数据,然后top++
}
/*清空栈*/ 
void ClearStack(SeqStack *S){
     S->top = 0;                    
}
/*判断栈是否为空*/
int isEmpty(SeqStack *S)
{
	return S->top == 0;
}

/*判断栈是否满*/  
int isFull(SeqStack *S)  
{  
    return S->top == StackSize;  
}  
   

动态分配的数组实现栈:并用栈解决禁止转换问题:(十进制转二进制或八进制)

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

#define STACK_INIT_SIZE 10 //定义最初申请的内存大小
#define STACK_INCREMENT 2  //每一次申请内存不足的时候扩展的内存大小

#define OVERFLOW 0
#define FALSE 0
#define TRUE 1
#define ERROR 0
#define INFEAIBLE 0 //不可实行的
#define OK 1

typedef int SElemType;
typedef int Status;

int Length;

/*****************结构类型部分******************/
typedef struct Stack
{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;  //sequence stack顺序栈

/*****************构造一个空栈**********************/
Status InitStack(SqStack &S)
{
	if( !( S.base = (SElemType *)malloc( STACK_INIT_SIZE * sizeof(SElemType) ) ) )
		exit(OVERFLOW);  //存储分配失败
	
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;  //初始栈容量
	
	return OK;
}

/******************压入栈元素*********************/
Status Push(SqStack &S, SElemType e)//这里不是SElemType &e
{
	//栈满追加内存
	if(S.top - S.base >= S.stacksize){
		S.base = (SElemType *) realloc(S.base, sizeof(SElemType) * (S.stacksize + STACK_INCREMENT));
		if(!S.base)
			exit(OVERFLOW);
		//给SqStack的三个对象赋值
		S.top = S.base + S.stacksize;
		S.stacksize += STACK_INCREMENT; 
	}
	*S.top++ = e;//先把e压入栈顶,S.top再增加1指向栈顶元素e的下一个位置
	return OK;
}
/******************输出栈元素*********************/
void PrintList(SqStack S)
{
	S.top = S.base;
	for( int i = 0; i< Length; i++){
		printf("%d\n",*(S.top) ++);
	}
}
/******************判断栈是否为空*****************/
Status StackEmpty(SqStack S)
{
	if(S.base == S.top) return true;
	else return false;
}
/******************删除栈顶元素*******************/
Status Pop(SqStack &S, SElemType &e)
{
	//判断是否为空
	if( S.base == S.top ) return ERROR;
	
	e = *--S.top;
	return OK;
}

/********************进制转换********************/
int conversion(unsigned int n,unsigned int m)//十进制数转化成m进制
{
	SqStack s;
	InitStack(s);
	int e = 0;

	unsigned result = 0;
	while(n)
	{
		Push(s, (SElemType)n%m);
		n /= m;
	}
	while( !StackEmpty(s))
	{
		Pop(s,e);
		result = result*10 + e;
	}
	return result;
} 

int main()
{
	int n = 123;
	int m = 2;
	int result = conversion(n,m);
	printf("%d\n", result);
	return 0;
}






  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 欢迎!如果您想要实现非递归方式的快速排序算法,可以按照以下步骤: 1. 选择一个基准元素(通常选择数组的第一个元素)。 2. 将数组划分为两个子数组,小于等于基准元素的放在左边,大于基准元素的放在右边。 3. 对左右两个子数组分别执行步骤1和步骤2,直到子数组的长度为1或0。 具体实现过程中,可以使用两个指针left和right来标记当前子数组的起始和终止位置,然后交换元素以实现划分。同时,使用一个来记录待排序子数组的起始和终止位置,用于实现非递归。 以下是一个示例代码: ```python def quick_sort(arr): if len(arr) <= 1: return arr stack = [(0, len(arr) - 1)] while stack: left, right = stack.pop() if left >= right: continue pivot = arr[left] i, j = left, right while i < j: while i < j and arr[j] > pivot: j -= 1 while i < j and arr[i] <= pivot: i += 1 arr[i], arr[j] = arr[j], arr[i] arr[left], arr[i] = arr[i], arr[left] stack.append((left, i - 1)) stack.append((i + 1, right)) return arr ``` 希望对您有所帮助! ### 回答2: 快速排序是一种常用的排序算法,它利用分治的思想将一个数组分成较小和较大的两个子数组,然后递归地对这两个子数组进行排序。传统的快速排序算法通常使用递归方式实现,但也可以使用非递归方式实现,以下是基于C语言的非递归快速排序算法的实现过程: 1. 首先定义一个(Stack)来保存待处理的子数组的起始位置和结束位置。 2. 初始化,并将整个数组的起始位置和结束位置入。 3. 进入循环,并从中取出一个待处理的子数组。 4. 在当前的子数组中选择一个基准元素(通常选择第一个元素),将数组按照基准元素的大小分成两部分。 5. 分别用两个指针从数组的两端开始扫描,当两个指针相遇时,停止扫描。 6. 将左指针指向的元素与基准元素交换,然后基准元素的位置就确定了。 7. 将左右两个子数组的起始位置和结束位置入。 8. 继续进行下一轮的循环,直到为空。 9. 最后,数组排序完成。 这种非递归的实现方式可以避免递归调用的额外开销,提高了排序的效率。同时,使用保存待处理的子数组实现了迭代处理的效果。 以上就是基于C语言的非递归方式实现快速排序的简要步骤,请根据需要进行具体的编码实现。 ### 回答3: 快速排序(QuickSort)是一种常用的排序算法,它的原理是在待排序的数组中选择一个元素作为基准(通常选择第一个元素),然后将数组划分为两部分,左边部分的元素都比基准小,右边部分的元素都比基准大,然后对左右两个部分再分别进行快速排序,如此递归处理,直到整个数组有序为止。 下面是使用非递归方式实现快速排序的步骤: 1. 使用一个来保存每个待处理的子数组的左右边界,初始时将整个数组的左右边界入。 2. 进入循环,直到为空为止。 3. 从中取出一个元素作为当前待处理的子数组的左右边界。 4. 如果子数组的长度小于等于1,则无需排序,跳过当前循环。 5. 选择子数组的第一个元素作为基准。 6. 使用左右指针分别指向子数组的左右边界。 7. 左指针向右移动,直到找到一个大于基准的元素。 8. 右指针向左移动,直到找到一个小于基准的元素。 9. 如果左指针小于等于右指针,则交换左右指针所指向的元素,并将左指针右移,右指针左移。 10. 继续重复步骤 7~9,直到左右指针相遇。 11. 将基准元素与左指针所指向元素交换。 12. 将子数组的左右边界入,按照右边界、左边界的顺序入。 13. 将子数组较长的一边的边界入,较短的一边的边界不入。 14. 继续下一次循环。 通过以上步骤,可以实现非递归方式的快速排序。使用来保存待处理的子数组的边界,在每一次循环中,取出一个子数组的边界,对子数组进行划分排序,然后根据划分的结果将子数组的边界入,继续下一次循环,直到为空,完成排序过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值