主頁 > 軟體設計 > 資料結構-表

資料結構-表

2021-01-02 12:37:28 軟體設計

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

線性表

基本概念

定義(性質相同的資料元素構成的有限序列)

表長,空表,位序,直接前驅,直接后繼

基本操作(12)

InitList(&L); //構造一個空的線性表L
ListEmpty(L); //判斷線性表L是否是空表,若是,則回傳TRUE,否則回傳FALSE
ListLength(L); //回傳線性表L的長度
GetElem(L,i,&e) ; //用e回傳線性表L的第i個資料元素的值
LocateElem(L,e,compare());//在線性表L中查找第一個和元素e滿足compare關系//的元素,若找到則回傳其位序;否則回傳0
PriorElem(L,e, &pre_e); //用pre_e回傳線性表L中元素e的直接前驅
NextElem(L, e, &next_e); //用next_e回傳線性表L中元素e的直接后繼
ListInsert(&L,i,e) ; //將資料元素e插入到線性表L的第i個資料元素之前
ListDelete(&L,i,&e); //洗掉線性表L的第i個資料元素,并將其值用e回傳
ListTraverse(L,visit()); //依次對線性表L中的每個元素呼叫visit進行訪問
ClearList(&L); //重置線性表L為空表
DestroyList(&L); //銷毀線性表L,可能的話釋放其空間

存盤結構

順序表

用一組地址連續的存盤單元依次存盤線性表的資料元素,用順序存盤結構表示的線性表又稱為順序表,

  • 存盤型別定義
  #define LIST_INIT_SIZE 100 //順序表存盤空間的初始分配量
  #define LISTINCREMENT 10  //順序表存盤空間的分配增量
  typedef struct
  {     ElemType *elem;  //存盤空間的基地址
       int length;    //順序表的當前長度
       int listsize;   //陣列存盤空間的長度
  }SqList;
  • 特點

    • 邏輯上相鄰的資料元素在物理位置上也相鄰
    • 隨機存取
  • 基本操作

    • 初始化順序表
	  Status InitSqList(SqList& L) //順序表初始化
	  {
	    L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));//申請初始分配空間
	    if (L.elem == NULL) exit(OVERFLOW);//分配失敗,回傳OVERFLOW
	    L.length = 0;//初始化表長為零
	    L.listsize = LIST_INIT_SIZE;//初始化陣列存盤空間為初始分配空間
	    return OK;//分配成功回傳OK
	  }
- 銷毀順序表
	  void DestroySqList(SqList& L)//銷毀順序表
	  {
	    if (L.elem != NULL)//如果順序表存在
	      free(L.elem);//釋放存盤空間
	    L.elem = NULL;//存盤空間基址置空
	  }
- 順序表判空
	  Status SqListEmpty(SqList L)//順序表的判空操作
	  {
	    if (L.length == 0) 
	      return TRUE;//表長為零為空表
	    else 
	      return FALSE;//表長非零不為空
	  }
- 順序表求表長
	  int SqListLength(SqList L)//順序表求表長
	  {
	    return L.length;
	  }
- 獲取元素
	  Status GetSqElem(SqList L, int i, ElemType& e)//取第i個元素,用第三個引數e回傳 
	  {
	    if (i<1 || i>L.length)//判斷索引是否有效
	      return ERROR;//無效報錯
	    else
	    {
	      e = L.elem[i - 1];//有效則回傳元素
	      return OK;
	    }
	  }
- 定位操作
	  int SqLocateElem(SqList L, ElemType e)//定位元素e,回傳元素位序,若元素不存在則回傳零
	  {
	    int i;
	    for (i = 1; i <= L.length; i++)//遍歷陣列
	    {
	      if (L.elem[i - 1] == e);//找到元素跳出回圈
	        break;
	    }
	    if (i <= L.length)//判斷是否溢位
	      return i;
	    else
	      return 0;
	  }
- 插入操作
	  Status SqListInsert(SqList& L, int i, ElemType e)//順序表插入操作,在位序i上插入元素e
	  {
	    if (i<1 || i>L.length)//判斷位序是否有效
	      return ERROR;
	    if (L.length == L.listsize)//判斷是否溢位,如果溢位,重新分配空間
	    {
	      L.elem = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT) * sizeof(ElemType));
	      if (!L.elem) exit(OVERFLOW);
	      L.listsize += LISTINCREMENT;
	    }
	    ElemType* q;
	    q = &L.elem[i - 1];
	    for (ElemType* p = &L.elem[L.length - 1]; p >= q; p--)//從后向前移動元素
	    {
	      *(p + 1) = *p;
	    }
	    *q = e;
	    L.length++;//更新表長
	    return OK;
	  }
- 洗掉操作
	  Status SqListDelete(SqList& L, int i)//洗掉順序表第i個元素
	  {
	    if (i<1 || i>L.length) //判斷引數是否溢位
	      return ERROR;
	    int j;
	    for (j = i; j < L.length; j++)//從第i+1個元素開始到最后一個元素遍歷
	    {
	      L.elem[j - 1] = L.elem[j];//每個元素向前移
	    }
	    L.length--;
	    return OK;
	  }
- 遍歷操作
	  Status SqListTraverse(SqList L, Status(*visit)(ElemType))//順序表遍歷操作
	  {
	    int i;
	    for (i = 0; i < L.length; i++)//回圈遍歷順序表
	      if (visit(L.elem[i])==FALSE) //遍歷例外退出
	        return ERROR;
	    return OK;
	  }
	  定義比較函式:
	  Status equal(ElemType a,ElemType b){
	     if(a==b) return TRUE;
	     else return FALSE;
	  }
  • 優缺點

    • 優點:可以隨機存取表中任一元素; 大部分操作都比較容易實作;存盤利用率高(關系隱含在存盤結構里,不需顯式表示)
    • 缺點:不知道表的規模的情況下,2個常量的大小不太好確定;順序表在進行插入和洗掉操作時,需要移動大量元素,浪費大量時間,
  • 順序表應用

    • 把2個非遞減有序的順序表LA和LB歸并為非遞減有序的線性表LC
	  void MergeList_Sq(SqList la,SqList lb,SqList &lc){//演算法2.7
	    pa=la.elem; pb=lb.elem;
	    lc.listsize=lc.length=la.length+lb.length;
	    pc=lc.elem = new ElemType[lc.listsize];
	    pa_last=la.elem+la.length-1;  pb_last=lb.elem+lb.length-1;
	    while(pa<=pa_last && pb<=pb_last) {
	  	if(*pa<=*pb) *pc++=*pa++;
	  	else *pc++=*pb++;
	    }
	    while(pa<=pa_last) *pc++=*pa++; 
	    while(pb<=pb_last) *pc++=*pb++;
	   }
- 順序表的就地逆置
	  void reverse1(Sqlist &A)
	  {
	  	 for(i=0,j=A.length-1;i<j;i++,j--)
	  	  A.elem[i]<->A.elem[j];
	  }//reverse1

鏈表

用一組任意的存盤單元(可連續可不連續)存盤線性表中的資料元素,

  • 單鏈表

    線性單鏈表:n個結點(每個結點只包含一個指標域)鏈接而成的鏈表,

    • 存盤型別定義
	  typedef struct LNode {
	  	ElemType data;    //資料域
	  	struct LNode* next; //指標域
	  }LNode, * LinkList;
- 特點

	- 任何兩個元素的存盤位置沒有固定的聯系
	- 每個元素的存盤位置只能由其直接前驅結點的指標指出
	- 鏈表是順序存取的存盤結構

- 特殊節點

	- 頭結點
	- 首元結點
	- 尾元結點

- 基本操作

	- 初始化單鏈表鏈表
		  Status InitLinkList(LinkList& L) //初始化鏈表
		  {
		    L = (LinkList)malloc(sizeof(LNode));//申請頭節點
		    if (L == NULL) exit(OVERFLOW);//申請失敗回傳例外
		    L->next = NULL;//頭節點置空
		    return OK;
		  }
	- 單鏈表的判空操作
		  Status LinkListEmpty(LinkList L) //單鏈表的判空操作
		  {
		    if (L->next == NULL)//判斷頭指標是否為空
		      return TRUE;
		    else 
		      return FALSE;
		  }
	- 銷毀單鏈表
		  void DestroyLinkList(LinkList& L) //銷毀單鏈表
		  {
		    LinkList p;//新建節點指標
		    while (L != NULL)//頭指標非空
		    {
		      p = L->next;//p指標保留將要釋放的節點指標域
		      free(L);//釋放節點
		      L = p;//更新頭節點
		    }
		  }
	- 單鏈表求表長
		  int LinkListLength(LinkList L) //單鏈表求表長操作
		  {
		    LinkList p;
		    int n = 0;
		    for (p = L->next; p != NULL; p = p->next, n++);//從首元節點遍歷單鏈表并計數
		    return n;
		  }
	- 清空單鏈表
		  void ClearLinkList(LinkList L) //清空單鏈表
		  {
		    LinkList p;
		    for (p = L->next; p != NULL; p = L->next)//從首元節點遍歷釋放節點空間
		    {
		      L->next = p->next;//更新頭節點指標
		      free(p);//釋放首元節點
		    }
		  }
	- 單鏈表取值
		  Status GetLinkElem(LinkList L, int i, ElemType& e) //單鏈表取第i個值,由e回傳
		  {
		    int count;//計數變數
		    LinkList p = L;//遍歷指標初始為頭指標
		    for (count = 0; count < i && p != NULL; count++)//計數器置零,遍歷到第i個,指標為空例外退出
		    {
		      p = p->next;
		    }
		    if (i > count)//判斷是否例外退出
		      return ERROR;
		    else//正常退出回傳OK
		    {
		      e = p->data;
		      return OK;
		    } 
		  }
	- 單鏈表定位
		  LinkList LinkLocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType)) 
		  //單鏈表定位操作,回傳第一個滿足關系的節點指標,若無滿足關系的元素,回傳空指標
		  {
		    LinkList p = L->next;//從首元節點遍歷鏈表
		    while (p!=NULL && compare(p->data, e)==FALSE) //直到滿足關系或遍歷結束停止遍歷
		      p = p->next;
		    return p;//回傳指標
		  }
	- 單鏈表插入操作
		  Status LinkListInsert(LinkList& L, int i, ElemType e)//單鏈表插入操作
		  {
		    int count;//計數變數
		    LinkList p;//回圈指標
		    for (count = 0, p = L; count < i - 1 && p != NULL; p = p->next, count++);//定位第i-1個節點
		    if (i < 0 || count < i - 1) //判斷i取值是否合理
		      return ERROR;
		    else
		    {
		      LinkList q;
		      q = (LinkList)malloc(sizeof(LNode));//創建待插入節點空間
		      q->data = e;
		      q->next = p->next;//插入節點指向其后繼
		      p->next = q;//連接其前驅節點
		    }
		    return OK;
		  }
	- 單鏈表洗掉操作
		  Status LinkListDelete(LinkList& L, int i)
		  {
		    int count;//計數變數
		    LinkList p;//回圈指標
		    for (count = 0, p = L; count < i - 1 && p != NULL; p = p->next, count++);//定位第i-1個節點
		    if (i < 0 || count < i - 1) //判斷i取值是否合理
		      return ERROR;
		    else
		    {
		      LinkList q = p->next;//指向待洗掉節點
		      p->next = q->next;//前驅節點指標域更新
		      free(q);//洗掉節點
		    }
		    return OK;
		  }
	- 遍歷單鏈表
		  Status LinkListTraverse(LinkList L,Status(*visit)(ElemType)) //遍歷單鏈表
		  {
		    LinkList p;
		    for (p = L->next; p; p = p->next)
		      if (!visit(p->data)) return ERROR;
		    return OK;
		  }
- 應用

	- 逆向建立n個元素的單鏈表 
		  void CreateList_backward(LinkList &L,int n)
		  { //逆向建立n個元素的單鏈表  
		   L=( LinkList) malloc(sizeof(LNode));
		   L->next=NULL;
		   for(i=0; i<n; i++)
		   { p=( LinkList) malloc(sizeof(LNode));
		     scanf(&p->data);  
		     p->next=L->next; 
		     L->next=p;  
		   }//for
		  }// CreateList_backward
- 優缺點

	- 優點:鏈表在進行插入和洗掉操作時,不再移動大量元素,僅需修改指標;不再需要定義2個常量
	- 缺點:元素只能順序存取;大部分操作的時間復雜度都為O(n);存盤利用率較低(存盤元素時要附帶存盤指標)
  • 回圈鏈表

    • 優點:從表中任一結點出發都可找到表中其他結點,

    • 操作

      和線性鏈表基本一致,差別在于判空和判表尾條件

      • 判空: L->next==L

      • 表尾:p->next==L

      • 在帶頭結點的回圈鏈表中設定尾指標可方便某些操作

        • 查找尾元結點
        • 查找首元結點
    • 應用

      • 兩個回圈鏈表合并

        僅設尾指標的回圈鏈表
        p=LA->next;
        LA->next=LB->next->next;
        free(LB->next);
        LB->next=p;
        LA=LB;

  • 雙向鏈表

    • 雙向鏈表C語言描述
	  typedef struct DulNode{
	    ElemType data;
	    Struct DulNode *prior;//指向其直接前驅的指標域
	    Struct DulNode *next; //指向其直接后繼的指標域
	  }DulNode,*DuLinkList;
- 操作

  某些操作演算法與線性單鏈表的操作相同;
  插入、洗掉等操作需同時修改兩個方向的指標

	- 插入
		  Status ListInsert_Dul(DuLinklist &L,int i,ElemType e)
		  {
		    if(!(p=GetElem_DuL(L,i)))
		  return ERROR;
		  if(!(s=(DuLinkList)malloc(sizeof(DuLNode))))
		  return ERROR;
		  s->data=e;
		  ① s->prior=p->prior;
		  ② p->prior->next=s;
		  ③ s->next=p;
		  ④ p->prior=s;
		    return OK;
		  }
	- 洗掉
		  Status ListDelete_Dul(DuLinklist &L,int i,ElemType &e)
		  {
		    if(!(p=GetElem_DuL(L,i)))
		  return ERROR;
		  e=p->data;
		  ① p->prior->next=p->next ;
		  ② p->next->prior=p->prior;free(p);
		    return OK;
		  }

堆疊和佇列

堆疊

基本概念

堆疊:限制僅在表的一端進行插入和洗掉的線性表

  • ADT定義

    ADT Stack {
    資料物件:D={ai| ai ? ElemSet, i=1,2,…,n, n?0}
    資料關系:R={< ai-1, ai >| ai-1,ai ?D,i=2,…,n}
    約定an端為堆疊頂, a1端為堆疊底
    基本操作:InitStack(&S); StackEmpty(S);
    StackLength(&S); GetTop(S, &e);
    Push(&S, e); Pop(&S, &e);
    ClearStack(&S);
    StackTraverse(S, visit());
    DestroyStack(&S);
    } ADT Stack

  • 堆疊頂:允許插入、洗掉的一端,

  • 堆疊底:與堆疊頂相對的另一端,

  • 空堆疊:表中沒有元素的堆疊

存盤結構

  • 順序堆疊

    特點:用一組地址連續的存盤單元依次存放自堆疊底到堆疊頂的資料元素
    堆疊中元素可動態增刪,即堆疊長是可變的,因此和順序表一樣,用動態分配的一維陣列來表示順序堆疊

    • 存盤結構的定義
	  #define STACK_INIT_SIZE 100 //順序堆疊存盤空間的初始分配量
	  #define STACKINCREMENT 10  //順序堆疊存盤空間的分配增量
	  
	  typedef struct
	  {
	  	SElemType* base; //堆疊底指標,始終指示存盤空間的基址
	  	SElemType* top; //堆疊頂指標,指向堆疊頂元素的下一個位置
	  	int stacksize;  //陣列存盤空間的長度
	  }SqStack;//順序堆疊定義
	- 堆疊底指標,始終指示存盤空間的基址
	- 堆疊頂指標,指向堆疊頂元素的下一個位置
	- 陣列存盤空間的長度

- 基本操作

	- 構造空堆疊
		  Status InitSqStack(SqStack& S)
		  { 
		  	S.base = (SElemType*)malloc((STACK_INIT_SIZE) * sizeof(SElemType));// 堆疊的連續空間分配
		  	if (!S.base)
		  	{
		  		exit(OVERFLOW);
		  	}
		  	S.top = S.base; //空堆疊,初始化堆疊頂指標
		  	S.stacksize = STACK_INIT_SIZE;
		  	return OK;
		  }//構造一個空堆疊,該堆疊由指標S指示
	- 銷毀堆疊
		  Status DestroySqStack(SqStack& S)
		  {
		  	if (S.base) //堆疊底指標非空
		  		free(S.base);
		  	S.base = NULL;
		  	return OK;
		  }//銷毀堆疊
	- 清空堆疊
		  Status ClearSqStack(SqStack& S)
		  {
		  	S.top = S.base;
		  	return OK;
		  }//清除堆疊
	- 判空
		  Status SqStackEmpty(SqStack S)
		  {
		  	return S.top == S.base;
		  }//堆疊的判空操作
	- 求堆疊長
		  int SqStackLength(SqStack S)
		  {
		  	return S.top - S.base;
		  }//求堆疊長
	- 取堆疊頂元素
		  Status GetTopSq(SqStack S, SElemType& e)
		  {
		  	if (S.top == S.base) return ERROR;
		  	e = *(S.top - 1);
		  	return OK;
		  } //用指標e帶回堆疊頂元素
	- 入堆疊
		  Status SqPush(SqStack& S, SElemType e)
		  {//入堆疊,插入元素e為新的堆疊頂元素
		  	if (S.top - S.base == S.stacksize)//堆疊滿
		  	{
		  		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		  		if (!S.base) exit(OVERFLOW);
		  		S.top = S.base + S.stacksize;
		  		S.stacksize += STACKINCREMENT;
		  	}//重新分配更大的連續空間
		  	*S.top++ = e;
		  	return OK;
		  }//Push
	- 出堆疊
		  Status SqPop(SqStack& S, SElemType& e)
		  {
		  	if (S.top == S.base) //堆疊空
		  		return ERROR;
		  	--S.top;
		  	e = *S.top;
		  	return OK;
		  }//出堆疊,洗掉的堆疊頂元素用指標e指示
	- 遍歷
		  Status SqStackTraverse(SqStack S, Status(*visit)(SElemType))
		  {//從堆疊底到堆疊頂依次對堆疊S中的每個資料元素呼叫visit
		   //指向的函式進行訪問
		  	SElemType* p;
		  	for (p = S.base; p < S.top; p++)
		  		if (!visit(*p)) return ERROR;
		  	return OK;
		  }// 堆疊的遍歷

  • 鏈堆疊

    • 鏈堆疊型別定義
	  typedef struct SNode{
	    SElemType data;   //資料域
	    struct SNode *next; //指標域
	  }SNode,*LinkStack;
	- 由于堆疊頂的位置特殊,所以鏈堆疊的頭指標指向堆疊頂元素所在結點
	- 注意:不必設頭結點

- 基本操作

	- 鏈堆疊入堆疊
		  Status Push(LinkStack &S, SElemType e)
		  {//插入e到堆疊S中使之成為新的堆疊頂元素
		   p=( LinkStack)malloc(sizeof(SNode));  
		   if(!p) 
		     exit(OVERFLOW);
		   p->data=e;   
		   p->next=S;  
		   S=p;  
		   return OK;
		  }//Push
	- 鏈堆疊出堆疊
		  Status Pop(LinkStack &S, SElemType &e)
		  {//若堆疊不空則出堆疊,洗掉的堆疊頂元素用e指示 
		    if(!S) 
		     return ERROR; //堆疊空
		    p=S; 
		    S=S->next;
		    e=p->data;
		    free(p);
		    return OK;
		  }//Pop

堆疊的應用

  • 數制轉換
  • 括號匹配的檢驗
  • 迷宮求解
  Typedef struct { //堆疊的元素型別定義
     int ord; //通道塊在路徑上的“序號”
     PosTpye seat ; //通道塊在迷宮中的“坐標位置”
     int di;  //從此通道塊走向下一通道塊的“方向”
  }SElemType;  
    
  Status MazePath(MazeType maze, PosType start, PosType end){
     InitStack(s); curpos=start; //設定當前位置為入口位置
     curstep =1;
     do{ 
      if(Pass(curpos)) { //當前位置可通
        FootPrint(curpos);  //留下足跡
        e=(curstep, curpos, 1);
        push(s,e);      //加入路徑
        if(curpos==end) return(TRUE); //到達終點
        curpos= NextPos(curpos, 1); 
        //下一位置是當前位置的東鄰
        curstep++;  //探索下一步//if
      else { //當前位置不能通過
        if (!StackEmpty(S)) {  
  Pop(S,e);
  while(e.di==4 && !StackEmpty(s)){
    MarkPrint(e.seat); Pop(s,e); 
  //留下不能//通過的標記,并退回一步//while
    if (e.di<4){
     e.di++; Push(S,e); //換下一方向搜索
     curpos=NextPos(e.seat, e.di);
     //設定當前位置是該新方向上的相鄰塊
    }//if
   }//if
  }//else
  } while(!StackEmpty(S));
  return(FALSE);
  }// MazePath
  • 算術運算式求值
  OperandType EvaluateExpression(){
   InitStack(OPTR); Push(OPTR, '#');
   InitStack(OPND); c=getchar();
   while(c!= '#' || GetTop(OPTR)!= '#'){
    if (!In(c,OP)) {Push(OPND,c); c=getchar();}
    else 
     switch(Precede(GetTop(OPTR),c)){
      case '<': Push(OPTR,c); c=getchar(); break;
      case '=': Pop(OPTR,x); c=getchar(); break; 
      case '>': Pop(OPTR,theta); 
  		  Pop(OPND,b); Pop(OPND,a);
  		  Push(OPND,Operate(a,theta,b)); break; 
     }//switch
   }//while
   return GetTop(OPND);
  }// EvaluateExpression
  • 堆疊與遞回

佇列

基本概念

只允許在表的一端進行插入,而在另一端進行洗掉的線性表,

  • ADT

    ADT Queue {
    資料物件:D={ai | ai ? ElemSet, i=1,2,…,n, n>=0}
    資料關系:R={< ai-1, ai > | ai-1, ai ?D, i=2,3,…,n}
    約定a1端為隊頭,an端為隊尾
    基本操作:InitQueue(&Q); QueueEmpty(Q);
    QueueLength(Q); GetHead(Q, &e);
    EnQueue(&Q, e); DeQueue(&Q, &e);
    ClearQueue(&Q);
    QueueTraverse(Q, Visit());
    DestroyQueue(&Q);
    }ADT Queue

  • 隊頭:允許洗掉的一端

  • 隊尾:允許插入的一端

  • 空佇列:沒有元素的佇列

  • 雙端佇列:限定插入和洗掉操作在表兩端進行的線性表

  • 輸出受限佇列:一端允許插入和洗掉,另一端只允許插入,

  • 輸入受限佇列:一端允許插入和洗掉,另一端只允許洗掉,

存盤結構

  • 鏈佇列

    使用二個指標分別記錄隊頭和隊尾的當前位置
    設立一個頭結點,并令頭指標指向頭結點,頭結點的指標域指向隊頭元素所在的結點
    鏈佇列的判空條件:頭指標和尾指標均指向頭結點

    • 鏈佇列型別定義
	  typedef struct QNode{
	   QElemType data;
	   struct QNode *next;
	  }QNode,*QueuePtr;
	  typedef struct {
	   QueuePtr front; //頭指標
	   QueuePtr rear;  //尾指標
	  }LinkQueue;
- 基本操作

	- 鏈佇列入隊
		  Status EnQueue(LinkQueue &Q, ElemType e)
		  { 
		   p=(QueuePtr)malloc(sizeof(QNode));  
		   if(!p) exit(OVERFLOW);
		   p->data=e; p->next=NULL;  
		   Q.rear->next=p;  
		   Q.rear=p;  //尾指標指向新的尾結點
		   return OK;
		  }// EnQueue
	- 鏈佇列入出隊
		  Status DeQueue(LinkQueue &Q, ElemType &e)
		  {
		    if(Q.rear == Q.front) return ERROR;
		    p=Q.front->next; 
		    e=p->data;  
		    Q.front->next=p->next;  
		    if(Q.rear==p) Q.rear=Q.front; 
		  //若隊頭元素是佇列中唯一的一個元素, 則洗掉該結點后//還需要修改尾指標,讓它指向頭結點
		    free(p); 
		    return OK;    
		   } // DeQueue
  • 順序佇列

    • 普通順序佇列

      用一組地址連續的存盤單元依次存盤從隊頭到隊尾的資料元素,

      • 順序佇列型別定義
		  #define MAXQSIZE 100
		  typedef struct {
		    QElemType *base; //存盤空間基地址
		    int front;//隊頭指標,指向隊頭元素
		    int rear;//隊尾指標,指向隊尾元素的下一個位置
		  }SqQueue;
	- 假上溢現象

- 回圈佇列

	- 存盤結構定義

		- 少用一個元素空間,約定佇列頭指標在隊尾指標下一個位置為佇列滿
			  #define MAXQSIZE 100
			  typedef int QElemType;
			  typedef struct {
			  	QElemType* base; //存盤空間基地址
			  	int front;//隊頭指標,指向隊頭元素
			  	int rear;//隊尾指標,指向隊尾元素的下一個位置
			  }SqQueue;
		- 另設標志位區別佇列空、滿
			  typedef struct {
			    ElemType *base;
			    int front;
			    int rear;
			    int tag;
			  }SqQueue;
	- 基本操作

		- 初始化佇列
			  Status InitSqQueue(SqQueue& Q)//初始化佇列
			  {
			  	Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
			  	if (Q.base == NULL)
			  		exit(OVERFLOW);
			  	Q.front = Q.rear = 0;//隊頭隊尾指標都指向0
			  	return OK;
			  }
		- 求隊長
			  int SqQueueLength(SqQueue Q)//求隊長
			  {
			  	return(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
			  }
		- 進隊
			  Status EnSqQueue(SqQueue& Q, QElemType e)//進隊操作
			  {
			  	if ((Q.rear + 1) % MAXQSIZE == Q.front) //佇列滿的判定條件(防止隊滿和隊空無法區分,留下一個位置不用
			  		return ERROR; //隊滿直接報錯,不再申請更大的記憶體
			  	else
			  	{
			  		Q.base[Q.rear] = e;
			  		Q.rear = (Q.rear + 1) % MAXQSIZE;//隊尾指標后移,%MAXQSIZE使下標首尾相接
			  		return OK;
			  	}
			  }
		- 出隊
			  Status DeQueue(SqQueue& Q, QElemType& e)//出隊操作
			  {
			  	if (Q.front == Q.rear) //隊空的判定條件
			  		return ERROR; //隊空報錯
			  	else
			  	{
			  		e = Q.base[Q.front];
			  		Q.front = (Q.front + 1) % MAXQSIZE;
			  		return OK;
			  	}
			  }
		- 判空
			  Status SqQueueEmpty(SqQueue Q)//回圈佇列的判空操作
			  {
			  	if (Q.rear == Q.front)
			  		return TRUE;
			  	else
			  		return FALSE;
			  }
		- 取隊頭元素
			  Status GetSqHead(SqQueue Q, QElemType& e)//取隊頭元素
			  {
			  	if (Q.rear == Q.front)
			  		return ERROR;
			  	else
			  	{
			  		e = Q.base[Q.front];
			  		return TRUE;
			  	}
			  }
		- 清空佇列
			  Status ClearSqQueue(SqQueue& Q)//清空佇列
			  {
			  	Q.rear = Q.front;
			  	return OK;
			  }
		- 銷毀佇列
			  Status DestroySqQueue(SqQueue& Q)//銷毀佇列
			  {
			  	free(Q.base);
			  	Q.front = Q.rear = 0;
			  	return OK;
			  }
		- 佇列的遍歷
			  Status SqQueueTraverse(SqQueue Q, Status (*visit)(QElemType))
			  {	
			  int i;
			  for (i = Q.front; i != Q.rear; i = (i + 1) % MAXQSIZE)
			  {visit(Q.base[i]);}
			  	return OK;
			  }

基本概念及術語

概念

  • 串:由零個或多個字符組成的有限序列,記為:s= ‘a1 a2…an’ (n>=0)

  • 串名: s

  • 串值: a1a2a3……an

  • 串長: n

  • 空串:串長為0的串,用Φ表示

  • 子串:串中任意個連續的字符組成的子序列

    • 串是其自身的子串
    • 空串是任意串的子串
  • 主串:包含子串的串

  • 字符在串中的位置:字符在串中的序號

  • 子串在主串中的位置:子串的第1個字符在主串中的位置

  • 空格串:由一個或多個空格組成的串,其長度為空格個數

  • 串相等:兩個串長度相等且各個對應位置的字符也相等

ADT

ADT String {
資料物件:D={ai| ai ?CharacterSet, i=1,2,…,n, n?0}
資料關系:R1={< ai-1 ,ai >| ai-1 , ai ? D,i=2,3,…,n}
基本操作:
StrAssign(&T, chars); StrCopy(&T,S);
StrEmpty(S); StrCompare(S,T);
StrLength(S); ClearString(&S);
Concat(&T,S1,S2); Substring(&Sub, S, pos,len);
Index(S,T,pos); Replace(&S,T,V);
StrInsert(&S, pos, T); StrDelete(&S, pos, len);
DestroyString(&S);
}ADT String;

基本操作

最小操作子集

  • 串賦值StrAssign
  • 串比較StrCompare
  • 求串長StrLength
  • 串聯接Concat
  • 求子串SubString

其他操作

  • 串拷貝StrCopy
  • 串判空StrEmpty
  • 定位串Index
  • 串替換Replace
  • 串插入StrInsert
  • 串洗掉StrDelete
  • 串清空ClearString
  • 銷毀串DestroyStr

串的表示方法

順序存盤結構

  • 定長存盤結構

    • 特點:用長度固定的連續單元依次存盤串值的字符序列
    • 以下標為0的陣列分量存放實際串長——PASCAL
    • 串值后加一個不計入串長的結束標記字符——C、C++中用‘\0’作串的結束標記
  • 堆分配存盤結構

    • 特點:采用動態字符陣列存放串值,此時不必為陣列預定義大小,以串長動態分配陣列空間
    • 資料型別定義
	  typedef struct {
	    char *ch; 
	    int length;  
	  }HString;

鏈式存盤結構

  • 塊鏈結構

    • 資料型別定義
	  #define CHUNKSIZE 80 // 可由用戶定義的塊大小
	   typedef struct Chunk { // 結點結構
	    char ch[CUNKSIZE];
	    struct Chunk *next;
	   } Chunk;
	   typedef struct { // 串的鏈表結構
	     Chunk *head, *tail; //串的頭和尾指標,便于聯結操作
	     int  curlen;      // 串的當前長度
	   } LString;

串的應用

文本編輯

  • 實質:修改字符資料的形式或格式
  • 基本操作:輸入、查找、修改、洗掉、輸出

陣列和廣義表

陣列

陣列的定義

  • ADT

    ADT Array {
    資料物件:ji=0, …, bi – 1, i = 1, 2, …, n,
    D={ | ∈ElemSet }
    資料關系:R = {R1, R2, …, Rn}
    Ri={ |0 ≤ jk ≤ bk–1, 1 ≤ k ≤n且
    k!=i, 0 ≤ ji ≤ bi–2, ∈D, i=1,2,…,n}
    基本操作:
    InitArray(&A, n, bound1, …, boundn)
    DestroyArray(&A)
    Value(A, &e, index1, …, indexn)
    Assign(&A, e, index1, …, indexn)
    }ADT Array

  • n維陣列是線性表的擴展

    • 當n=1,n維陣列退化成順序表
    • 當n>1,n維陣列可看成表中資料元素是n-1維陣列的線性表

陣列的順序表示

因為陣列一般不做插入/洗掉操作,所以用順序結構表示陣列是很自然的,

  • 特點:用一組地址連續的存盤單元按照某種規則存放陣列中的資料元素,

  • 2種順序(順序存盤方式)

    • 以行序為主(低下標優先法)
    • 以列序為主(高下標優先法)
  • 元素地址的計算

    • 要素

      • ①陣列的起始地址(即基地址)
      • ②陣列維數和各維的長度;
      • ③陣列中每個元素所占的存盤單元
    • 計算方法

      • 二維

        • 行主序:LOC(i,j) = LOC(0,0) + ( b2*i + j ) * L

        • 列主序:LOC(i,j) = LOC(0,0) + ( b1*j + i ) * L

        • 二維陣列元素地址的通式

          • 行優先存盤時的地址公式為:

            • LOC(aij)=LOC(ac1,c2)+[(i-c1)*(d2-c2+1)+j-c2)]*L
          • 列優先存盤的通式為:

            • LOC(aij)=LOC(ac1,c2)+[(j-c2)*(d1-c1+1)+i-c1)]*L
      • 多維

        • 設各維長度分別為b1, b2, b3, …, bn,每個元素占L個存盤單元, 起始地址是LOC(0,0,…,0)
        • LOC (j1,j2,…,jn ) = LOC(0,0,…,0) + (b2b3bn * j1+ b3b4*…bn * j2+ ……+ bnjn-1 + jn ) * L
    • 隨機存盤結構

      陣列元素的存盤位置是其下標的線性函式,由于計算各個元素存盤位置的時間相等,所以存盤陣列中任一元素的時間也相等,具有這一特點的存盤結構為隨機存盤結構,

  • 實作

  #define MAX_ARRAY_DIM 8
  typedef struct {
  	ElemType	*base;		//存盤空間基址
  	int	dim;		      //陣列維數
  	int	*bounds;		//陣列維界基址
  	int	*constants;	      //陣列映象函式常量{Ci}基址
  } Array;

矩陣的壓縮存盤

壓縮存盤:為多個值相同的元素只分配一個存盤空間,對零元素不分配空間,

  • 特殊矩陣:值相同的元素或零元素在矩陣中分布有一定規律,如三角矩陣、對角矩陣,

    • 對稱矩陣

      n階矩陣A中元素滿足性質a[i][j]=a[j][i] (1 ≤i, j≤ n)

      • 壓縮存盤

        為每一對對稱元素分配 個存盤空間. n2 ?n(n+1)/2
        用行主序的下(上)三角陣來存盤對稱矩陣的元素,
        sa[k](0 ≤ k ≤ n(n+1)/2-1) 為對稱矩陣的壓縮存盤結構

    • 上(下)三角陣

      下(上)三角(不含對角線)元素為常數c或0的n階矩陣

      • 壓縮存盤

        存盤上(下)三角中的元素和常數c
        用行主序存盤上(下)三角陣的元素
        sak 為上(下)三角陣的壓縮存盤結構

    • 對角矩陣

      所有非零元素都集中在以主對角線為中心的帶狀區域,其他元素為0,

      • 壓縮存盤

        用行主序存盤帶狀區域的非0元素

  • 稀疏矩陣:值相同的元素或零元素在矩陣中分布沒有一定規律,

    • 稀疏因子

      設m行n列的矩陣含t個非零元素,定義δ=t/(m*n)為稀疏因子,則? ? 0.05 的矩陣為稀疏矩陣,

    • 稀疏矩陣的壓縮存盤

    • 表示

      • 三元組( i,j,aij )

        • 三元組的C語言描述
			  typedef struct {
			     int i,j;
			     ElemType e;
			  }Triple;
		- 三元組順序表的C語言描述
			  #define MAXSIZE 1250 
			  typedef struct{
			     Triple data[MAXSIZE+1]; //data[0]未用
			     int mu,nu,tu;
			  }TSMatrix;
	- 行邏輯鏈接的順序表

	  需求:隨機存取任意一行的非0元
	  方法:記住矩陣每一行第一個非0元在三元組順序表中的位置
	  設陣列rpos[1..n]:矩陣中每行第一個非零元素的起始位置
	  rpos[1]=1;
	     rpos[row]=rpos[row-1]+第row-1行的非零元素個數
	  第i行所有非0元在data中的位置:rpos[i]..rpos[i+1]-1
	  行邏輯鏈接順序表:在稀疏矩陣的三元組順序表中設定指示行資訊的輔助陣列rpos
	  typedef struct{
	   Triple data[MAXSIZE+1];
	   int rpos[MAXRC+1];//各行第1個非零元位置表,rpos[0]未用
	   int mu,nu,tu;
	  }RLSMatrix;

	- 十字鏈表

- 轉置

	- 稀疏矩陣轉置方法一
		  Status TransposeSMatrix(TSMatrix M,TSMatrix &T)
		  {  T.mu=M.nu;T.nu=M.mu;T.tu=M.tu;
		     if(T.tu)
		     {  q=1;
		       for(col=1;col<=M.nu;++col)
		         for(p=1;p<=M.tu;++p)
		         if(M.data[p].j==col){
		           T.data[q]=(M.data[p].j, M.data[p].i, M.data[p].e); 
		  	    ++q;} 
		    } return OK;
		  }//TransposeSMatrix
	- 稀疏矩陣轉置方法二
		  Status FastTransposeSMatrix(TSMatrix M,TSMatrix &T)
		  { T.mu=M.nu;T.nu=M.mu;T.tu=M.tu;
		    if(T.tu) 
		    { for(col=1;col<=M.nu;++col) num[col]=0;
		      for(t=1;t<=M.tu;++t) ++num[M.data[t].j];
		      cpot[1]=1;
		      for(col=2;col<=M.nu;++col) 
		         cpot[col]=cpot[col-1]+num[col-1];
		      for(p=1;p<=M.tu;++p) {
		        col=M.data[p].j; q=cpot[col];
		        T.data[q]=( M.data[p].j, M.data[p].i, M.data[p].e );  
		        ++cpot[col];    }//for
		    }//if
		    return OK;
		  }//FastTransposeSMatrix

廣義表

定義

廣義表(串列):n (?0)個元素組成的有限序列,記作
LS = (α1, α2, …, αn)
其中αi 可以是單個元素(原子),也可以是廣義表(子表)

  • 表頭(head):n>0時,廣義表的第一個元素
  • 表尾(tail):除第一個元素外的所有其它元素組成的表
  • 空表:n = 0 的廣義表
  • 廣義表長度:廣義表中元素的個數
  • 廣義表深度:廣義表中括號的重數

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/243620.html

標籤:其他

上一篇:Java教程(一)---JDK和Maven安裝配置

下一篇:圖片資源服務器?一小時手寫http服務器提供資源服務

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more