1. 程式人生 > 其它 >基礎服務管理篇(三)——firewalld防火牆

基礎服務管理篇(三)——firewalld防火牆

//順序表實現
#define MaxSize 50
typedef int ElemType;
typedef struct
{
	ElemType data[MaxSize];//陣列
	int top;
}SqStack;

void InitStack(SqStack& S)
{
	S.top = -1;//棧為空
}
bool StackEmpty(SqStack S)
{
	if (-1 == S.top)
		return true;
    else
		return false;
}

bool Push(SqStack& S, ElemType x)
{
	if (S.top == MaxSize - 1)//棧滿
	{
		return false;
	}
	S.data[++S.top] = x;//++S.top  = -1,一開始為空棧“-1” -1+1=0 S.data[0]=x,依次走
	return true;
}

//獲取棧頂元素
bool GetTop(SqStack S, ElemType& x)
{
	if (StackEmpty(S))//棧為空
	{
		return false;
	}
	x = S.data[S.top];
	return true;
}

bool Pop(SqStack& S, ElemType& x)
{
	if (StackEmpty(S))//棧為空
	{
		return false;
	}
	x = S.data[S.top--];//等價於x=S.data[S.top]; S,top--;
	return true;

}

假設以Ⅰ和О分別表示入棧和出棧操作。棧的初態和終態均為空,入棧和出棧的操作序列可表示為僅由Ⅰ和О組成的序列,可以操作的序列稱為合法序列,否則稱為非法序列。寫出一個演算法,判定所給的操作序列是否合法。若合法,返回true,否則返回false(假定被判定的操作序列已存入一維陣列中).

設被判定的操作序列已存入一維陣列A中。演算法的基本設計思想:依次逐一掃描入棧出棧序列(即由“I”和“O”組成的字串),每掃描至任一位置均需檢查出棧次數(即“O”的個數)是否小於入棧次數(“I”的個數),若大於則為非法序列。掃描結束後,再判斷入棧和出棧次數是否相等,若不相等則不合題意,為非法序列。

int Judge(char A[])
{
    //判斷字元陣列A中的輸入輸出序列是否是合法序列,如是,返回true,否則返回false
    int i=0;		//i為下標
    int j=k=0;		//j和k分別為字母I和O的個數
	while(A[i]='\0')	//未到字元陣列尾
    {
        switch(A[i]){
        	case 'I': j++;	   break;	//入棧次數加1 
    	    case 'O': k++;
        		if(k>j) {printf("非法序列\n");exit(0);}              
        }  
        i++;		//不論A[i]是“I”或者是“O",指標i均後移
    }

    if(j!=k){
        printf("序列非法");
        return false;
    }
    else{
        printf("序列合法\n");
        return true;
    }
}

設單鏈表的表頭指標為L,結點結構由data和next兩個域構成,其中data域為字元型。試設計演算法判斷該連結串列的全部n個字元是否中心對稱。例如xyx、xyyx都是中心對稱。

演算法思想:使用棧來判斷連結串列中的資料是否中心對稱。讓連結串列的前一半元素依次進棧。在處理連結串列的後一半元素時,當訪問到連結串列的一個元素後,就從棧中彈出一個元素,兩個元素比較,若相等,則將連結串列中的下一個元素與棧中再彈出的元素比較,直至連結串列到尾。這時若棧是空棧,則得出連結串列中心對稱的結論;否則,當連結串列中的一個元素與棧中彈出元素不等時,結論為連結串列非中心對稱,結束演算法執行

演算法先將“連結串列的前一半”元素(字元)進棧。當n為偶數時,前一半和後一半的個數相同;當n為奇數時,連結串列中心結點字元不必比較,移動連結串列指標到下一字元開始比較。比較過程中遇到不相等時,立即退出while迴圈,不再進行比較。

int dc(LinkList L,int n){
    //L是帶頭節點的n個元素單鏈表,本演算法判斷連結串列是否是中心對稱
    int i;
    chars s[n/2];			//s字元棧
    p=L->next;			//p是連結串列的工作指標,指向待處理的當前元素
    for(i=0;i<n/2){		//連結串列前一半元素進棧
        s[i]=p->data;
	    p=p->next;
    }
    i--;				//恢復最後的i值
    if(n%2==1)			//若n是奇數,後移過中心結點
        p=p->next;
    while(p!=NULL&&s[i]==p->data){//檢測是否中心對稱
        i--;						//i充當棧頂指標
       	p=p->next;
    }
    if(i==-1)
        return 1;
    else
        return 0;
}

設有兩個棧s1、s2都採用順序棧方式,並共享一個儲存區〔0...., maxsize-1],為了儘量利用空間,減少溢位的可能,可採用棧頂相向、迎面增長的儲存方式。試設計s1、s2有關入棧和出棧的操作演算法。

兩個棧共享向量空間,將兩個棧的棧底設在向量兩端,初始時,s1棧頂指標為-1,s2棧頂指標為maxsize。兩個棧頂指標相鄰時為棧滿。兩個棧頂相向、迎面增長,棧頂指標指向棧頂元素。

#define maxsize 100		//兩個棧共享順序儲存空間所能達到的最多元素樹,初始化為100
#define elemtp int		//假設元素型別為整型
typedef struct{
    elemtp stack[maxsize];
    int top[2];
}stk;
stk s;		//s是如上定義的結構型別變數,為全域性變數

本題的關鍵在於,兩個棧入棧和退棧時的棧頂指標的計算。s1棧是通常意義下的棧;而s2棧入棧操作時,其棧頂指標左移(減1),退棧時,棧頂指標右移(加1).此比外,對於所有棧的操作,都要注意

(1)入棧操作

int push(int i,elemtp x)
{
    //入棧操作。i為棧號,i表示左邊的是s1棧,i=1表示右邊的s2棧,x是入棧元素
    //入棧成功返回1,否則返回0
    if(i<0||i>1){
        printf("棧號輸入不對");
        exit(0);
    }
    if(s.top[1]-s.top[0]==1{
        printf("棧已滿\n");
        return 0;
    }
       switch(i){
           case 0: s.stack[++s.top[0]]=x;return 1; break;
           case 1: s.stack[--s.top[1]]=x;return -1;
       }
}

(2)退棧操作

elemtp pop(int i){
    //推展演算法 i代表站好,i=0時為s1棧,i=1時為s2棧
    //退棧成功返回退棧元素,否則返回-1
    if(i<0||i>1){
        printf("棧號輸入錯誤\n");
        exit(0);
    }
    switch(i){
        case 0:
            if(s.top[0]==-1){
                printf("棧空\n");
                return -1;      
            }     
        case 1:
            if(s.top[1]==maxsize){
                printf("棧空\n");
                    return -1;
            }
            else
                return s.stack[ss.top[1]++];
            break;
    }//switch
}