热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

目录一丶栈的概念和类型定义1:栈的基本概念2:抽象数据类型层面的栈1)栈的数据元素2)栈

目录

一丶栈的概念和类型定义

1:栈的基本概念

2:抽象数据类型层面的栈

1)栈的数据元素

2)栈的基本操作

3)C#中的栈类

二丶栈的存储结构及实现

1:栈的顺序存储结构和操作实现

1)栈的初始化

2)返回栈中元素个数

3)判断栈为空或满

4)入栈

5)出栈

6)获取栈顶元素的值

7)显示栈中所有数据元素的值

2:栈的链式存储结构及操作实现

1)栈的初始化

2)返回栈的元素个数

3)判断栈状态为空或满

4)入栈

5)出栈

6)获取栈顶元素值

3:栈的应用举例

1)基于栈结构的函数嵌套调用

2)应用栈结构的典型例子

三丶队列的概念及类型应用

1:队列的基本概念

2:抽象数据类型层面的队列

1)队列的数据元素

2)队列的基本操作

3:C#中的队列类

四丶队列的存储结构及实现

1:队列的顺序存储结构及操作实现

1)队列的顺序存储结构

2)顺序循环队列的定义及操作

1)队列初始化

2)返回队列的元素个数

3)判断队列的状态是否为空或满

4)入队

5)出队

6)获取队首对象,但不移除

7)输出队列中所有数据元素

2:队列的链式存储结构及操作实现

1)队列初始化

2)返回队列的元素个数

3)判断队列的状态是否为空或满

4)入队

5)出队

6)获取队首对象,但不移除

3:队列的应用举例



一丶栈的概念和类型定义

栈和队列是两种特殊的线性结构,其数据元素之间也具有顺序的逻辑关系。与线性表可以在表中任意位置进行插入和删除操作不同,栈和队列的插入和删除操作限制在特殊的位置。

栈具有后进先出的特性,队列具有先进先出的特性。在实现方式上,栈和队列都可以采用顺序存储结构和链式存储结构。

1:栈的基本概念

栈(stack)是一种特殊的线性数据结构,栈结构中的数据元素之间具有顺序的逻辑结构,但栈只允许在数据集合的一断进行插入和删除数据的操作。

向栈中插入数据元素的操作称为入栈(push),从栈中删除元素称为出栈(pop)

栈就像某种只有单个出入口的仓库,每次只允许一件件地往里面堆货物,然后一件件地往外取货物,不允许从中间进行操作

2:抽象数据类型层面的栈


1)栈的数据元素

栈作为一种特殊地线性结构,可以如同线性表一样采用顺序存储结构和链式存储结构实现。

采用顺序存储结构实现的栈称为顺序栈(sequenced stack),采用链式存储结构实现的栈称为链式栈(Linked stack)

2)栈的基本操作

Initialize:栈的初始化

Count:数据元素计数

Empty:判断栈的状态是否为空

Push:入栈,该操作将一个数据元素插入栈中作为新的栈顶元素在入栈操作之前必须判断栈的状态是否已满,不满则直接入栈,否则会出现栈上溢错误(stack overflow exception)

Pop:出栈,该操作将取出栈顶元素

Peek:探测栈顶,获取栈顶数据元素,但不移除

3)C#中的栈类

在C#类库中定义了一个非泛型栈stack类和一个泛型栈stack类,栈类刻画了一种数据后进后出的集合,是常用的数据集合类型

例:利用栈进行数制转换

数制转换是计算机实现计算的一个基本问题。十进制数N和其他d进制数的转换具有以下关系:
},解决方法很多,其中一种算法如下:
N=(N/d)×d+N%d

例如,其运算如下:





























N       N/dN%d
24683084
308384
3846
404

现编写一个程序:用户输入任意一个非负十进制数,程序打印输出与其等值的八进制数

程序如下:

using System;
using System.Collections.Generic;
namespace stackqueuetest
{
public class DecOctConversion
{
public static void Main(string[] args)
{
int n=2468;
if(args.Length>0)
{
n=int.Parse(args[0]);
}
Stack s=new Stack(20);
Console.WriteLine("十进制数:{0}->八进制:",n);
while(n!=0)
{
s.Push(n%8);
n=n/8;
}
int i=s.Count;
while(i>0)
{
Console.Write(s.Pop());
i--;
}
Console.WriteLine();
}
}
}

输出结果为:

十进制数:2468->八进制:4644

上述程序中,我们使用了泛型栈类Stack定义了一个整型数组成的栈Stack对象s,Push操作要求的是整型数,Pop操作返回的类型也是整形,如果换用非泛型stack,那么它的操作要求是object类型的,所以在入栈和出栈都需要将整形实参装箱为object,然后拆箱为整型,频繁的装箱拆箱操作,会影响执行效率。


二丶栈的存储结构及实现

1:栈的顺序存储结构和操作实现

 顺序栈采用一组连续的存储空间存放栈的数据元素,可以用下面声明的sequenced stack类来实现栈:

public class SequencedStack
{
private T[] items;
private const int empty=-1;
private int top= empty;//top为栈顶元素下标,简称栈顶指针
....
}

SequencedStack类中的成员变量items定义为数组类型,即准备用数组存储栈的数据元素。

成员变量top指示当前栈顶数据元素在数组items中的下标,起栈顶指针的作用。

成员变量empty起符号常量的作用


1)栈的初始化

用类的构造方法初始化一个栈对象,在构造方法中为items数组变量申请指定大小的存储空间,以备用于存放栈的数据元素,通过使用top值为empty来设置栈初始状态为空(empty则定义为常量-1)

public SequencedStack(int n)
{
inems=new T[n];
top=empty; //设置栈初始状态为空
}
//缺省构造方法,不带参数时,构造具有16个存储单元的空栈
public SequencedStack():this(16){}

2)返回栈中元素个数

通过count来实现

public int Count
{
get{return top+1;}
}

3)判断栈为空或满

分别通过bool类型的属性Empty和Full来实现,编码如下:
 

public bool Empty
{
get{return top==empty;}
}
public bool Full
{
get{return Top>=item.Length-1;}
}

4)入栈

通过Push来实现入栈操作。当栈实例当前预分配的存储空间已满则需要调用本类中定义的私有方法DoubleCapcity重新分配空间,编码如下:

public void Push(T k)
{
if(Full)DoubleCapacity();
top++;顶端位置+1
items[top]=k 顶端加元素k
}
//扩充顺序栈的容量
private void DoubleCapacity()
{
int c=Count;
int capacity =2*items.Length;
T[]copy=new T[capacity];//按照新容量构造一个数组
for (int i=0;i {
copy[i]=items[i];
}
items=copy;//items指向新分配的空间
}

 如果栈顶分配的空间大小合理,栈处于非满的状态,则Push操作的时间复杂度为O(1),如果经常需要增加存储容量,则复杂度为O(n);

Push方法的形参k声明为T类型,即入栈的数据元素声明为T类型,在调用该操作时,实参的类型要与栈实例定义时声明的类型保持一致。例如定义s为SequencedStack类型,则以后入栈语句s.Push(k)的实参k必须为strin类型


5)出栈

定义Pop方法实现出栈操作,取出栈顶元素,并设定下一个元素为新的栈顶元素

public T Pop()
{
T k=default(T); //k初始化为缺省值
if(!Empty)
{
k=items[top];
top--;
return k;
}
else //栈为空
{
throw new InvalidOperationException("Stack is Empty:"+this.GetType());
}
}

6)获取栈顶元素的值

定义Peek方法实现探测栈顶元素值的操作.该操作获取栈顶元素,但不移除该数据元素,栈顶指针top不变。

public T Peek()
{
if(!Empty)
return items[top];
else
throw new InvalidOperationException("Stack is empty"+this.GetType());
}

7)显示栈中所有数据元素的值

当栈非空。从栈顶结点开始,直到栈底结点,依次显示各结点的值

public void Show(bool showTypeName=false)
{
if(showTypeName)
{
Console.WriteLine("SequencecStack:");
}
if(!Empty)
{
for(int i=this.top;i>=0;i--)
{
Console.Write(items[i]+" ");
}
Console.WriteLine();
}
}

比起在控制台显示信息,更为一般的操作,是以字符串的形式返回对栈对象而言有意义的值,这可以通过在顺序栈SequencedStack类重写(override)从object类继承的ToString的方法来实现。

public override string ToString()
{
StringBuilder s=new StringBuilder();
for(int i=this.top;i>=0;i--)
{
a.Append(items[i]);
s.Append(";");
}
return s.ToString();
}

例:调用栈的顺序栈的基本操作,测试SequencedStack类

namespace stackqueuetest
{
class SequencedStackTest
{
public static void Main(string[] args)
{
int i =0;
SequencedStack s1=new SequencedStack(20);
Console.Write("Push:");
while(i{
s1.Push(args[i]);
Console.Write(args[i]+" ");
i++;
}
s1.Show(true); //输出栈中各元素值
Console.Write("pop :");
string str;
while (!s1.Empty)
{
str.s1.Pop();
Console.Write(str+" ");
}
Console.WriteLine("栈中的元素个数为{0}",s1.Count);
}
}
}

2:栈的链式存储结构及操作实现

声明LinkedStack类实现栈的链式存储

namespace DSA
{
public class LinkedStack:SingleLinkedList
{
private SingleLinkedNodetop;
...
}
}

这里的新类LinkedStack是作为前一章定义的类SIngleLinkedList的子类来定义的 

1)栈的初始化

用构造方法创建栈对象并对它进行初始化,它首先用jilei(SingleLinkedList)类的构造方法创建一条单向链表,接着将成员变量top指向第一个数据节点,设置栈的状态初始为空

2)返回栈的元素个数

由基类SingleLinkedList继承的公共属性Count即可完成返回栈的元素个数的功能

3)判断栈状态为空或满

用布尔属性Empty来实现判断栈是否为空的功能,实现代码如下:

public override bool Empty{get{return top==null;}}

4)入栈

定义Push方法实现入栈操作

为将插入的数据元素值k构造一个新结点q,在top指向的栈顶结点之前插入结点q作为新的栈顶结点,并使成员变量top指向它。入栈的数据元素是T类型,在调用该操作时,实参的类型要与栈实例定义时声明的元素类型保持一致。

采用动态分配方式为每一个新结点分配内存空间,方法的运算复杂度为O(1)

public void Push(T k)
{
SingleLinkedNodeq= new SingleLinkedNode(k);
q.next=top;
top=q;
base.Head.Next=top;
}

5)出栈

定义pop方法实现出栈操作

public T Pop()
{
T k=default(T); //置变量k为T类型的缺省值
if(!Empty) //栈不空
{
k=top.Item;//取得栈顶数据元素
top=top.Next; //删除栈顶元素
base.Head.Next=top;
return k;
}
else
{
throw new InvalidOperationException("stack is Empty:"+this.GetType());
}
}

6)获取栈顶元素值

定义peek操作来获取栈顶数据元素,运算复杂度为O(1);

public T Peek()
{
if(!Empty)
{
return top.Item;
}
else//栈为空时产生异常
{
throw new InvalidOperationException("stack is Empty:"+this.GetType());
}
}

3:栈的应用举例


1)基于栈结构的函数嵌套调用

程序中函数的嵌套调用是指在程序运行中,一个函数的执行语句序列中存在队另一个函数的调用,每个函数在执行完与函数调用后再返回到调用它的函数中继续执行,对于多层嵌套调用来说,函数返回的次序和函数调用的次序刚好相反,整个过程具有后进先出的特征,系统通过建立一个栈结构来协助实现这种函数嵌套调用机制。

例如:

执行函数A时,函数A中的某语句又调用了函数B,系统要做如下一系列的入栈操作:

①将调用语句后的下一条语句作为返回地址信息保存在栈中,,该过程为保存现场

②将函数A调用函数B的实参保存在栈中,该过程为实参压栈

③控制交给函数B,在栈中分配函数B的局部变量,然后开始执行函数B内的其他语句

函数B执行完毕后,系统要做一系列的如下出栈操作才能保证将系统控制返回到调用函数B的函数A中:

①退回栈中的函数B的局部分配的空间

②退回栈中为函数B的参数分配的空间

③取出保存在栈中的返回地址信息,该过程为恢复现场


2)应用栈结构的典型例子


判断C#表达式中括号是否匹配

在高级编程语言的表达式中,括号一般都是要求左右匹配的,对于一个给定的表达式,可用栈来辅助判断其中括号是否匹配。

假设在C#语言的表达式中,只能出现圆括号用以改变运算次序,而且圆括号是左右匹配的。

本例声明MatchExpBracket类,对于一个字符串expstr,方法MatchingBracket(expstr)判断字符串expstr中的括号是否匹配,例如,当字符串expstr保存表达式((9-1)*(3+4))时,MatchingBracket()方法的算法描述:第一个"("入栈,第二个"("入栈,遇到")"时,出栈一个"(",表达式检测完后,栈为空即可。

方法MatchingBracket()的实现算法描述如下:

-》1:设NextToken是待检测字符串expstr的当前字符,s1是算法设置的一个栈:
若NextToken是左括号,则NextToken入栈;

若NextToken是右括号,则从s1中出栈一个符号,若为左括号,表示括号匹配

-》2:重复上一步,检测结束后,若栈为空,则表示括号匹配,否则缺少右括号。

代码段如下:

using System;
namespace stackqueuetest
{
public class MathExpBracket
{
public static void Main(string[] args)
{
string expstr1="((9-1)*(3+4))";
Console.WriteLine(expstr1);
Console.WriteLine("Matching Bracket: "+MatchingBracket(expstr1));
}
public static string MatchingBracket(string expstr)
{
SequencedStack s1= new SequencedStack(30);
char NextToken,outToken;
int i=0;bool LlrR=true;
while(LlrR&&i{
NextToken=expstr[i];
i++;
switch (NextToken) {
case'(' : //遇到左括号时,入栈
s1.Push(NextToken);
break;
case')':
if(s1.Empty)
{
LlrR=false;
}
else
{
OutToken=s1.pop;
if(!OutToken.Equals('('))
{
LlrR=false;
}
}
break;
}
}
if(LlrR)
{
if(s1.Empty)
return"OK!";
else
return"期望)!";
}
else
return"期望(!";
}
}
}

程序运行结果:

((9-1)*(3+4))

Matching Bracket:期望)!


三丶队列的概念及类型应用

1:队列的基本概念

与栈一样,队列(queue)也是一种常用的线性数据结构,它的元素之间具有顺序的逻辑关系。

它具有“先进先出(first in first out)”特性的数据结构

2:抽象数据类型层面的队列


1)队列的数据元素

队列作为一种特殊的线性结构,可以如同线性表及栈一样,采用顺序存储结构和链式存储结构实现。

顺序存储结构实现的队列称为顺序队列(Sequenced queue),链式存储结构实现的队列称为链式队列(Linked Queue)

2)队列的基本操作

Initializi:队列的初始化。创建一个队列实例,并进行初始化操作,例如设置队列状态为空

Count:队列元素计数

Empty:判断队列是否为空

Full:判断队列的状态是否已满

Enqueue:入队。该操作将新的数据元素从队尾加入对列。在入队以前必须进行判断队列是否已满,如果队列不满,则接受,如果已满则会产生上溢错误(queue overflow exception),或者为队列先分配更大的空间,然后接受新元素

Dequeue:出队。该操作取出队头的数据元素,下一个数据元素为新的队头元素。

在出队前必须进行判断队列是否为空,队列为空则会产生下溢错误(queue underflow exception)

Peek:探测队首。获得队首数据元素,但不移除,队头指针保持不变

3:C#中的队列类

在C#的类库中定义了一个非泛型队列Queue类和一个泛型队列Queue类,队列类刻画了一种数据先进先出的集合

例:创建字符串类型的队列对象并向其添加若干值,打印出队列的内容

using System;
using System.Collections.Generic;
namespace stackqueuetest
{
public class SamplesQueue
{
public static void Main()
{
Queue q= new Queue();
q.Enqueue("F");
q.Enqueue("S");
q.Enqueue("T");
Console.WriteLine("queue");
Console.WriteLine("\tConunt :{0}",q.Count);
Console.WriteLine("\tValue: {0}", q);
foreach(string o in q)
{
Console.Write("{o}\t",o);
}
Console.WriteLine();
}
}
}

四丶队列的存储结构及实现

1:队列的顺序存储结构及操作实现


1)队列的顺序存储结构

顺序队列用一组连续的存储结构存放队列的数据结构,可以用SequencedQueue类来实现顺序队列,SequencedQueue类中的成员变量items定义为数组,用以存储加入队列的数据元素;成员变量front和rear分别作为队首元素在数组items中的位置下标和下一个将入队的数据元素将占据的存储单元的位置下标,构成了队首指针和队尾指针

用该类定义和构造的对象就是一个个具体的队列实例

public class SequencedQuene
{
private T[]items;
private int front,rear;
...
}

front是队头的数据元素的下标,简称队头下标;rear是下一个入队的数据元素将占据的存储单元的位置下标。

元素入队或者出队时,需要相应修改front和rear变量的值:一个元素入队时,rear+1,而一个元素出队时,front+1 

假设现在有三个数据元素(a,b,c)已入队,那么frOnt=0,rear=3

接着ab两个元素出队,此时frOnt=2,rear=3

接着两个新元素d和e入队,此时frOnt=2,rear=5

假设数组items的长度为5,此时如果有新的数据元素入队,那么应该存放在rear指示的位置,但是此时rear为5,数组下标越界而产生溢出,这是一种假溢出

要解决假溢出,应该将顺序队列设计成逻辑上的“环形”结构,看似是一种顺序循环队列

2)顺序循环队列的定义及操作

为实现顺序队列循环利用存储空间,进行入队和出队操作时,front和rear不是简单的+1,而是应该+1后再作取模运算

rear=(rear+1)%items.Length;

frOnt=(front+1)%items.Length;

顺序循环队列的操作为SequencedQueue类的方法和属性成员予以实现

①队列初始化

用类的构造方法初始化一个队列对象,在构造方法中首先为items数组变量申请指定大小的存储空间,以备用来存放队列的数据元素;接着设置队列初始状态为空,frOnt=0,rear=0

public SequencedQueue(int n)
{
items=new T[n+1];
frOnt=rear=0;
}
public sequencedQueue():this(16){}

②返回队列的元素个数

使用Count来实现

public int Count
{
get{return(rear-front+items.Length)%items.Length;}
}

③判断队列的状态是否为空或满

使用Empty和Full来实现,当frOnt==rear时,表明其中没有数据元素,队列为空,编码如下:

public bool Full
{
get{return frOnt==(rear+1)%items.Length;}
}

④入队

定义Enqueue方法来实现,如果队列当前预分配的存储空间已装满数据元素,在后续的操作前,需要调用本类中定义的私有方法DoubleCapacity重新分配空间,将原数组中的数据元素逐个拷贝到新数组,并相应调整队首和队尾指针,实现代码如下:

public void Enqueue(T k)
{
if(Full)DoubleCapacity();
items[rear]=k;
raer=(rear+1)%items.Length;
}
private void DoubleCapacity()
{
int i,j;
int capacity=2*items.Length-1;
int count=Count;
T[]copy=new T[capacity] //按照新容量构建一个数组
for(i=0;i {
j=(i+front)%items.Length;
copy[i]=items[j];
}
frOnt=0;
rear=count;
items=copy; //items指向新分配的空间
}

⑤出队

定义Dequeue方法来实现出队操作。需要先测试队列是否为空,当队列不为空时,取走front位置上的队首数据元素,front+1,新front位置上的数据元素成为新的队首数据元素,此方法的时间复杂度为O(1),编码如下:

public T Dequeue()
{
T k=default(T);
if(!Empty)
{
k=items[front];
frOnt=(front+1)%items.Length;
return k;
}
else
{
throw new InvalidOperationException("Queue is Empty:"+this.GetType())
}
}

⑥获取队首对象,但不移除

使用peek方法来进行该操作,当队列不为空时,取走front位置上的队首数据元素,front位置保持不变,运算复杂度为O(1),编码如下:

public T Peek()
{
if(!Empty)return items[front]
else
{
throw new IndexOutOfRangeException("Queue is empty:"+this.GetType)
}
}

⑦输出队列中所有数据元素

当队列非空,从队首结点开始,直到队尾结点,依次输出结点值,编码如下:

public void Show(bool showTypeName=false)
{
if(showTypeName)
Console.Write("SequencedQueue: ");
int i=this.front;
int n=i;
if(!Empty)
{
if(i {
n=this.rear-1;
}
else
{
n=this.rear+this.items.Length-1;
}
for(i=0;i<=n;i++)
{
Console.WriteLine(items[i%items.Length]+" ");
}
Console.WriteLine();
}
}

由此可见:顺序循环队列相比原始顺序队列的设计,有两方面的改进:

-①入队时只改变下标rear,出队时只改变下标front,它们都做“循环”移动,取值范围是0-items.Length-1,这样可以重复的使用队列内部的存储空间,避免“假溢出”

-②在队列中设立一个空位置,如果不设立一个空位置,则队列空和队列满两种状态的条件都是队头指针和队尾指针相等

例:测试顺序循环队列的操作实现

using System;
namespace stackqueuetest
{
class SequencedQueueTest
{
public static void Main(string[] args)
{
int i=0,n=2;
SequencedQueue q1=new SequencedQueue();
while(i{
Console.Write("Enqueue: "+(i+1)+"\t");
q1.Enqueue((i+1).ToString());
q1.Show(true);
q1.Enqueue(args[i]);//将命令行参数入队
Console.Write("Enqueue: "+args[i]+"\t");
q1.Show(true);
i++;
}
while(!q1.Empty)
{
Console.Write("Dequeue: ");
string str= q1.Dequeue();
Console.Write(str+" ");
Console.Write("\t");
q1.Show(true);
}
Console.WriteLine();
}
}
}

在控制台窗口可以用如下命令进行编译:

csc SequenedQueueTest.cs/r:...\stackqueue\bin\Debug\stackqueue.dll

从命令行输入参数运行SequencedQueueTest程序:

SequencedQueueTest HelloWorld

程序结果如下:

Enqueue:1                     SequeueQueue:1

.... 

2:队列的链式存储结构及操作实现

声明LinkedQueue类实现链式队列:

public class LinkedQueue
{
private SingleLinkedListitems;
private SingleLinkedNodefront,rear;
}

1)队列初始化

用构造方法创建一条准备用以存储队列数据的单向链表,设置队列的初始状态为空

public LinkedQueue()
{
items=new SingleLinkedList();
frOnt=items.Head.Next;
rear=items.Head;
}

2)返回队列的元素个数

使用Count来实现,编码如下:
 

public int Count;
{
get{return items.Count;}
}

 内嵌成员items的数据结点的个数(items.Count)也就是队列的元素个数

3)判断队列的状态是否为空或满

定义属性Empty来实现

public bool Empty
{
get{return(frOnt==null)&&(rear==items.Head);}
}

4)入队

定义Enqueue方法实现入队操作

public void Enqueue(T k)
{
SingleLinkedNodeq=new SingleLinkedNode(k);
rear.Next=q;
frOnt=items.Head.Next;
rear=q;
}

5)出队

定义Dequeue方法来实现出队操作,方法的运算复杂度为O(1).

public T Dequeue()
{
T k=default(T);//置变量k为T类型的缺省值
if(!Empty)
{
k=front.Item;//取得队头结点数据元素
frOnt=front.Next; //删除队头结点
items.Head.Next=front;
}
if(frOnt==null)
{
rear=items.Head;
}
return k;
else
{
throw new InvalidOperationException("Queue is Empty: "+this.GetType());
}
}

6)获取队首对象,但不移除

当队列不为空时,取走front位置上的队首数据元素,运算复杂度为O(1).

public T Peek()
{
if(!Empty)
return front.Item;
else
throw new InvalidOperationException("Queue is Empty: "+GetType());
}

3:队列的应用举例

队列是一种先进先出的特殊线性结构,可以作为求解具有“先进先出”特性的数学模型,因此队列结构成为解决相应问题算法设计的有力工具。

例:(解素数环问题)将1,2,...,n个数排成环形,使得每相邻两数之和为素数,构成一个素数环。

解决思路:依次试探每个数,用一个线性表存放素数环的数据元素,用一个队列存放等待检查的数据元素,依次从队列取出一个数据元素k与素数环最后一个数据元素相加,如果两个数之和为素数,则将k加入素数环中,否则暂时无法进入素数环,必须让他再次放入队列等待处理,重复上述操作,直到列表为空

本例应用顺序表SequencedList类和顺序队列SequencedQueue类。创建SequencedList类的一个线性表实例ring1,用以存放素数环的数据元素,创建SequecedQueue类的一个实例q1作为队列,存放待检测的数据元素,静态方法IsPrime(k)判断k是否为素数。

using System;
using System.Collections;
using System.Collections.Generic;
namespace stackqueuetest
{
public class PrimeRing
{
public static bool IsPrime(int k)
{
int j=2;
if(k==2)return true;
if(k<2||k>2&&k%2==0)return false;
else
{
j=3;
while(j {
j=j+2;
}
if(j>k)return true;
else return false;
}
}
public static void Main(string[] args)
{
int i,j,k,n=10;
SequencedQueue q1=new SequencedQueue(); //创建队列q1
SequencedList ring1=new SequencedList(); //创建线性表ring1表示素数环
ring1.Add(1);
for(i=2;iq1.Enqueue(i);
q1.Show(true);
i=0;
while(!q1.Empty)
{
k=q1.Dequeue();//出队
Console.Write("Dequeue:"+k+"\t");
j=ring1[i]+k;
if(IsPrime(j))
{
ring1.Add(k);
Console.Write("add into ring \t");
i++;
}
else
{
qi.Dequeue(k);
Console.Write("wait into ring \t");
}
qi.Show(true);
}
Console.WriteLine();
ring1.Show(true);
}
}
}



推荐阅读
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • Unity3D引擎的体系结构和功能详解
    本文详细介绍了Unity3D引擎的体系结构和功能。Unity3D是一个屡获殊荣的工具,用于创建交互式3D应用程序。它由游戏引擎和编辑器组成,支持C#、Boo和JavaScript脚本编程。该引擎涵盖了声音、图形、物理和网络功能等主题。Unity编辑器具有多语言脚本编辑器和预制装配系统等特点。本文还介绍了Unity的许可证情况。Unity基本功能有限的免费,适用于PC、MAC和Web开发。其他平台或完整的功能集需要购买许可证。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
author-avatar
水水2502919973
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有