第2章 順序表及其順序存儲

第2章 順序表及其順序存儲

1、線性表

  1. 線性表:屬於線性結構。有且僅有一個開始結點,有且僅有一個終端結點,其餘結點爲內部結點。
  2. 線性表的存儲:順序存儲 or 鏈式存儲

2、順序表

2.1 順序表的基本概念及描述

  1. 順序表:線性表採用順序存儲的方式
  2. 注:每一個結點佔用\(len\)個內存單元,\(location(k_i)\)爲順序表中第\(i\)個結點\(k_i\)所佔內存空間的第\(1\)個單元的地址
    1. \(location(k_i) = location(k_i) + len\)
    2. \(location(k_i) = location(k_1) + (i-1)len\)

2.2 順序表的實現

  1. 注:數組中下標爲\(i\)的元素對應的是順序表中第\(i+1\)個結點
  2. 順序表的經常使用操做(簡單且大機率不考,所以無代碼展現,後不提醒)
    1. 順序表的初始化
    2. 順序表後部進行插入操做
    3. 打印順序表的各結點值
    4. 判斷順序表是否爲空
    5. 查找順序表中值爲x的結點位置
    6. 取得順序表中第i個結點的值

2.2.1 順序表的存儲結構

#define MAXSIZE 100
typedef int datatype;
typedef struct{
  datatype a[MAZXSIZE];
  int size;
}sequence_list;

2.2.2 順序表的插入操做(程序)

  1. 將值爲\(x\)的結點插入到第\(i\)個位置的步驟:
    1. 判斷順序表是不是滿的
    2. 判斷指定的位置是否不存在
    3. \(k_i,\cdots,k_{n-1}\)這些結點對應的數組元素依次後移一個位置,空出\(k_i\)原先的位置存放新插入的結點。(從後往前移)
    4. 將值爲\(x\)的結點插入到第\(i\)個位置
    5. 順序表的長度加\(1\)
#define MAXSIZE 100
typedef int datatype;
typedef struct{
  datatype a[MAZXSIZE];
  int size;
}sequence_list;

void insert(sequence_list *slt, datatype x, int position)
{
  int i;
  if (slt->size == MAXSIZE)
  {
    printf("\n順序表是滿的!無法插入!");
    exit(1);
  }
  if (position < 0 || position > slt->size) // 如size爲10,slt->a[i-1=9]存在,既能夠不用>=
  {
    printf("\n指定的插入位置不存在!");
    exit(1);
  }
  for (i = slt->size; i > position; i--)
  {
    slt->a[i] = slt->a[i-1];
  }
  slt->a[position] = x;
  slt->size++;
}

時間複雜度:\(O(n)\)c++

2.2.3 順序表的刪除操做(程序)

  1. 刪除順序表中第\(i\)個結點的步驟:
    1. 判斷順序表是否爲空
    2. 判斷刪除位置是否存在
    3. 將順序表中的\(k_{i+1},\cdots,k_{n-1}\)元素依次前移一個位置。(從前日後移)
    4. 順序表的長度減\(1\)
#define MAXSIZE 100
typedef int datatype;
typedef struct{
  datatype a[MAZXSIZE];
  int size;
}sequence_list;

void dele(sequence_list *slt, int position)
{
  int i;
  if (slt->size == 0)
  {
    pringf("\n順序表是空的!");
    exit(1);
  }
  if (position < 0 || position >= slt->size) // 如size爲10,postion爲10,slt->a[i+1=11]不存在,即不能夠>
  {
    printf("\n指定的刪除位置不存在!");
    exit(1);
  }
  for (i = position; i < slt->size-1; i++) // 循環到倒數第二個元素便可,由於後面是a[i+1]
  {
    slt->a[i] = slt->a[i+1];
  }
  slt->size--;
}

時間複雜度:\(O(n)\)算法

3、棧

3.1 棧的基本概念及描述

  1. 棧:特殊的線性表。插入運算和刪除運算均在線性表的同一端進行
  2. 棧頂:進行插入(進棧)和刪除(出棧)的一端
  3. 棧底:不進行操做的一端
  4. 棧的性質:後進先出(先進後出)

3.2 順序棧及其實現

  1. 棧(順序存儲)的經常使用操做:
    1. 棧的存儲結構
    2. 棧初始化
    3. 判斷棧是否爲空
    4. 取得棧頂結點值
    5. 棧的插入操做
    6. 棧的刪除操做

3.3 棧的應用之一(括號匹配)

  1. 括號匹配解決步驟:
    1. 從左向右掃描表達式
    2. 遇到開括號則將遇到的開括號存放於棧中
    3. 遇到閉括號則查看是否與棧頂結點匹配。匹配刪除棧頂結點,不匹配說明表達式中的括號是不匹配的(結束
    4. 掃描整個表達式後,棧是空的,說明表達式中的括號是匹配的;不然是不匹配的(結束

3.4 棧的應用之二(算術表達式求值)

  1. 中綴表達式:操做符處於兩個操做數之間
  2. 前綴表達式:操做符處於兩個操做數以前
  3. 後綴表達式:操做符處於兩個操做數以後
  4. 後綴表達式求值:每遇到一個操做符,則將前面的兩個操做數執行相應的操做
  5. 後綴表達式求解步驟:
    1. 把遇到的操做數暫存於一個棧中
    2. 遇到操做符,則從棧中取出兩個操做數執行相應的操做,並將結果壓入棧中
    3. 直到對後綴表達式中最後一個操做符處理完
    4. 最後壓入棧中的樹就是後綴表達式的計算結果

3.4.1 中綴表達式轉換爲後綴表達式步驟

  1. 從左到右掃描中綴表達式,若是是數字字符和圓點「.」,直接寫入後綴表達式數組

  2. 遇到開括號,將開括號壓入棧中,遇到匹配的閉括號,將棧中元素彈出並放入後綴表達式,直到棧頂元素爲匹配的開括號時,彈出該開括號post

  3. 遇到的是操做符:spa

    1. 遇到的操做符優先級<=棧頂元素,彈出棧頂元素放入後綴表達式(循環判斷)
    2. 遇到的操做符優先級>棧頂元素,將遇到的操做符壓入棧中
  4. 重複上述步驟,直到遇到結束標記「#」,彈出棧中的全部元素並放入後綴表達式數組中設計

  5. 操做符優先級:\(\#,(,+-,*/\)指針

-1 0 1 2
# ( +- */

4、隊列

4.1 隊列的基本概念及描述

  1. 隊列:一種特殊的線性表。插入(進隊)和刪除(出隊)操做分別在表的兩端進行
  2. 隊尾:插入的一端
  3. 對首:刪除的一端
  4. 隊列的性質:先進先出

4.2 順序隊列及其實現

  1. 隊列(順序存儲)的經常使用操做:
    1. 隊列的順序結構
    2. 隊列初始化
    3. 判斷隊列是否爲空
    4. 打印隊列的結點值
    5. 取得隊列的隊首結點值
    6. 隊列的插入操做
    7. 隊列的刪除操做

4.3 順序循環隊列及其實現

  1. 普通隊列的列滿狀態指標:\(rear = MAXSIZE\)
  2. 循環隊列的做用:在普通隊列處於列滿狀態時,利用數組前部的空閒位置
  3. 循環隊列的列滿狀態指標:
    1. 設置一個標誌:因爲\(rear\)\(1\)使\(rear = front\),爲隊滿;因爲\(front\)\(1\)使\(rear = front\),隊空
    2. 犧牲一個數組元素空間:\((rear + 1) \% MAXSIZE = front\),隊滿;\(rear = front\),隊空
  4. 循環隊列(順序存儲)的經常使用操做(相比較普通隊列在指針增\(1\)中增長一個取模操做):
    1. 循環隊列的插入操做
    2. 循環隊列的刪除操做

5、程序設計習題

5.1 順序表值爲x的結點的個數(程序)

設計一個算法,求順序表中值爲x的結點的個數code

程序步驟:隊列

  1. 設定初始值\(c\)計數
  2. 每找到一個值爲\(x\)的結點,計數加\(1\)
  3. 返回\(c\)
// 順序表的存儲結構定義以下(文件名seqlist.h)
#include <stdio.h>
#define N 100 // 預約義最大的數據域空間
typedef int datatype; // 假設數據類型爲整型
typedef struct{
  datatype data[N]; // 此處假設數據元素只包含一個整型的關鍵字域
  int length; // 線性表長度
}seqlist; // 預約義的順序表類型

// 算法countx(L, x)用於求順序表L中值爲x的結點的個數
int countx(seqlist *L, datatype x)
{
  int c = 0;
  int i;
  for (i = 0; i < L->length; i++)
  {
    if (L->data[i] == x) c++;
  }
	return c;
}

5.2 順序表倒置(程序)

設計一個算法,將一個順序表倒置。即,若是順序表各個結點值存儲在一維數組\(a\)中,倒置的結果是使得數組\(a\)中的\(a[o]\)等於原來的最後一個元素,\(a[1]\)等於原來的倒數第\(2\)個元素,\(\cdots\)\(a\)的最後一個元素等於原來的第一個元素內存

程序步驟:

  1. 定位最後一個元素
  2. \(t\)保留第個一元素的值,而且第一個元素和最後一個元素的值交換
  3. 循環到最後一個元素
// 順序表的存儲結構定義以下(文件名seqlist.h)
#include <stdio.h>
#define N 100 // 預約義最大的數據域空間
typedef int datatype; // 假設數據類型爲整型
typedef struct{
  datatype data[N]; // 此處假設數據元素只包含一個整型的關鍵字域
  int length; // 線性表長度
}seqlist; // 預約義的順序表類型

// 算法verge(L)用於順序表倒置
void verge(seqlist *L)
{
  int t, i, j;
  i = 0;
  j = L->length-1;
  while (i < j)
  {
    t = L->data[i];
    L->data[i++] = L->data[j];
    L->data[j--] = t;
  }
}

5.3 有序順序表插入結點並仍然有序-真題(程序)

已知一個順序表中的各結點值是從小到大有序的,設計一個算法,插入一個值爲\(x\)的結點,使順序表中的結點仍然是從小到大有序

程序步驟:

  1. 從最後一個元素開始與\(x\)比較大小,元素值大於該\(x\)值,則日後挪一個位置
  2. 找到比\(x\)小的元素中止
  3. 在該元素的位置上插入\(x\)
// 順序表的存儲結構定義以下(文件名seqlist.h)
#include <stdio.h>
#define N 100 // 預約義最大的數據域空間
typedef int datatype; // 假設數據類型爲整型
typedef struct{
  datatype data[N]; // 此處假設數據元素只包含一個整型的關鍵字域
  int length; // 線性表長度
}seqlist; // 預約義的順序表類型

// 算法insertx(L, x)用於有序順序表插入結點並仍然有序
void insertx(seqlist *L, datatype x)
{
  int j;
  if (L->length < N)
  {
    j = L->length - 1;
    while (j >= 0 && L->data[j] > x)
    {
      L->data[j+1] = L->data[j]; // 元素統一日後挪
      j--;
    }
    L->data[j+1] = x;
    L->length++;
  }
}
相關文章
相關標籤/搜索