1. 程式人生 > >C/C++線性表---順序表演算法全解析

C/C++線性表---順序表演算法全解析

課程筆記來源:

MOOC網

郝斌資料結構

之前學過一遍資料結構,面試時候真的忘光了,之前去華環讓寫一個簡單的連結串列刪除演算法也是沒有寫出來,想做CS,必須把資料結構學好了,還是再來一遍吧。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

順序表定義

順序表就是把線性表中的所有元素按照邏輯順序,依次儲存到從計算機儲存器中指定儲存位置開始的一塊連續儲存空間中。

順序表的儲存型別:線性表的首地址,線性表的總長度,線性表的有效長度。

優點:任意元素可以隨機存取

缺點:插入和刪除操作時候,需要移動大量元素

typedef struct Arr
{
    int *pBase; //線性表基地址相當於陣列首地址
    int len;  //線性表的總長度
    int cnt;  //線性表總有效元素
}SqList;

順序表的基恩演算法

初始化順序表
構造一個空的順序表,給線性表分配 len 個長度,有效長度 cnt 為0個。 注意:malloc分配時候,要進行成功與否的判斷。
void InitArr(SqList *pArr,int len)
{
  pArr->pBase = (int*)malloc(sizeof(int)*len);
  if(NULL == pArr)
  {
      printf("分配失敗\n");
      exit(-1);
  }
  pArr->cnt = 0;
  pArr->len = len;
}
判斷順序表是否為空
如果線性表的有效長度為 0 ,則線性表為空。
int is_empty(SqList *pArr)
{
    if( 0 == pArr->cnt)
        return true;
    else
        return false;
}
判斷線性表是否為滿
如果線性表的有效長度為 len ,則線性表為滿。
int is_full(SqList *pArr)
{
    if(pArr->cnt == pArr->len)
        return true;
    else
        return false;
}
線性表的遍歷
如果線性表為空,則無需輸出,否則用 for 迴圈遍歷輸出。
void showArr(SqList *pArr)
{
    int i;
    if( true ==is_empty(pArr))
    {
        printf("線性表元素為空\n");
    }
    else
    {
        for(i=0;i<pArr->cnt;i++)
            printf("%d\t",pArr->pBase[i]);
            puts("\n");
    }
}
線性表追加元素
如果線性表已經滿了,則無法新增;否則,新增元素,有效元素加1。 注意:新增完元素後,有效位加1。
void appendArr(SqList *pArr,int ele)
{
    if(is_full(pArr))
        printf("線性表已經滿了\n");
    else
    {
        pArr->pBase[pArr->cnt] = ele;
        pArr->cnt++;

    }
}
刪除指定位置元素
判斷是否為空,邏輯位置必須大於等於1,還必須小於等於cnt。從指定位置pos到cnt,依次向前移動一位。 注意:輸入的是邏輯位置,必須和ele下標位置區分開。可以舉個例子很好的區分開。
void deleteArr(SqList *pArr,int pos)
{
    int i;
    if(true == is_empty(pArr))
        printf("線性表是空\n");
    if(pos < 1 || pos > pArr->cnt)
        printf("輸入位置無效\n");
    else
    {
        for(i=pos;i<pArr->cnt;i++)
           pArr->pBase[i-1] = pArr->pBase[i];
        pArr->cnt--;
    }

}

指定位置新增元素 判斷是否為滿,位置必須在1和cnt+1
void insertEle(SqList *pArr,int pos,int ele)
{
   int i;
   if(is_full(pArr))
        printf("線性表已滿\n");
   if(pos<1 || pos > pArr->cnt+1)
        printf("刪除的位置無效\n");
   else
   {
       for(i= pArr->cnt-1;i>=pos-1;i--)
            pArr->pBase[i+1] = pArr->pBase[i];
       pArr->pBase[pos-1] =ele;
       pArr->cnt++;
   }
}


總體的C程式碼:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include <time.h>

#define ListMax 10
#define true     1
#define false    0

typedef struct Arr
{
    int *pBase; //線性表基地址相當於陣列首地址
    int len;  //線性表的總長度
    int cnt;  //線性表總有效元素
}SqList;

//線性表初始化
void InitArr(SqList *pArr,int len)
{
  pArr->pBase = (int*)malloc(sizeof(int)*len);
  if(NULL == pArr)
  {
      printf("分配失敗\n");
      exit(-1);
  }
  pArr->cnt = 0;
  pArr->len = len;
}
//判斷是否為空
int is_empty(SqList *pArr)
{
    if( 0 == pArr->cnt)
        return true;
    else
        return false;
}
//判斷是否滿了
int is_full(SqList *pArr)
{
    if(pArr->cnt == pArr->len)
        return true;
    else
        return false;
}
//線性表元素遍歷
void showArr(SqList *pArr)
{
    int i;
    if( true ==is_empty(pArr))
    {
        printf("線性表元素為空\n");
    }
    else
    {
        for(i=0;i<pArr->cnt;i++)
            printf("%d\t",pArr->pBase[i]);
            puts("\n");
    }
}
//線性表追加
void appendArr(SqList *pArr,int ele)
{
    if(is_full(pArr))
        printf("線性表已經滿了\n");
    else
    {
        pArr->pBase[pArr->cnt] = ele;
        pArr->cnt++;

    }
}
//刪除線性表
void deleteArr(SqList *pArr,int pos)
{
    int i;
    if(true == is_empty(pArr))
        printf("線性表是空\n");
    if(pos < 1 || pos > pArr->cnt)
        printf("輸入位置無效\n");
    else
    {
        for(i=pos;i<pArr->cnt;i++)
           pArr->pBase[i-1] = pArr->pBase[i];
        pArr->cnt--;
    }

}
//指定位置pos新增元素ele
//元素pos的位置是從 1 到 pArr->len
void insertEle(SqList *pArr,int pos,int ele)
{
   int i;
   if(is_full(pArr))
        printf("線性表已滿\n");
   if(pos<1 || pos > pArr->cnt+1)
        printf("刪除的位置無效\n");
   else
   {
       for(i= pArr->cnt-1;i>=pos-1;i--)
            pArr->pBase[i+1] = pArr->pBase[i];
       pArr->pBase[pos-1] =ele;
       pArr->cnt++;
   }
}
//得到指定位置的值
int getArr(SqList *pArr,int pos)
{
    if(true == is_empty(pArr))
        printf("線性表是空\n");
    if(pos < 1 || pos > pArr->cnt)
        printf("輸入位置無效\n");
    return pArr->pBase[pos-1];
}
//查詢第一個元素等於ele的邏輯號
int locateEle(SqList *pArr, int ele)
{
    int i=0;
    while(i<pArr->cnt && pArr->pBase[i]!= ele) i++;
    if(i >=pArr->cnt) return 0;
    else   return i+1;
}
//線性表元素倒置
void inversionArr(SqList *pArr)
{
    int i=0;
    int j=pArr->cnt-1;
    int temp;
    while(i<j)
    {
        temp = pArr->pBase[i];
        pArr->pBase[i] = pArr->pBase[j];
        pArr->pBase[j] = temp;
        i++;
        j--;
    }
}
//線性表排序
void sortArr(SqList *pArr,int m)
{
    switch(m)
    {
        case 1:  //氣泡排序
        {
            int i,j,temp;
            for(i=0;i<pArr->cnt-1;i++)
            {
                for(j=i+1;j<pArr->cnt;j++)
                {
                    if(pArr->pBase[i] > pArr->pBase[j])
                    {
                          temp = pArr->pBase[i];
                          pArr->pBase[i] = pArr->pBase[j];
                          pArr->pBase[j] = temp;
                    }
                }
            }

            break;
        }
        case 2:  //選擇排序
        {
          int n = pArr->cnt;
           while(n >1)
           {
              int i,temp,pos=0;
              int max=pArr->pBase[0];
              for(i=0;i<n;i++)
              {
                  if(max < pArr->pBase[i])
                  {
                      max = pArr->pBase[i];
                      pos = i;
                  }
              }
              temp = pArr->pBase[pos];
              pArr->pBase[pos] = pArr->pBase[n-1];
              pArr->pBase[n-1] = temp;
              n--;
           }
           break;
        }
        case 3: //插入排序
        {
            int i;
            for(i=1;i<pArr->cnt;i++)
            {
                int temp = pArr->pBase[i];
                while(i>0 && pArr->pBase[i-1] > temp)
                {
                   pArr->pBase[i] = pArr->pBase[i-1];
                   i--;
                }
                pArr->pBase[i] = temp;
            }

        }
    }
}
void main()
{

    int i;
    SqList arr;
    srand( (unsigned)time( NULL ) );
    InitArr(&arr, ListMax);
    for(i=0;i<7;i++)
        appendArr(&arr,rand()%100+1);
    showArr(&arr);
    insertEle(&arr,8,11);
    showArr(&arr);
    deleteArr(&arr,6);
    showArr(&arr);
    printf("%d\n",getArr(&arr,5));
    printf("%d\n",locateEle(&arr,4));
    inversionArr(&arr);
    sortArr(&arr,3);
    showArr(&arr);
}

C++程式碼: 使用了模板類,實現泛函,增強程式碼的重複性。
#include<iostream>
#include<stdlib.h>
#include<time.h>

#define MAXSIZE 20
using namespace std;

//使用模板類是為了實現泛型,
//使用模板類可以使用不同的資料型別
template <class T>
class SqList
{
public:
    SqList(){cnt = 0;}//無參建構函式
    SqList(T a[],int len);//有參建構函式
    ~SqList(){} //解構函式
    bool isEmpty();//是否為空
    bool isFull(); //是否滿了
    void showArr();  //順序表遍歷
    T    getArr(int pos); //得到指定位置元素 ele
    void appendArr(T ele);//順序表追加
    void deleteArr(int pos);//刪除指定位置元素
    void insertEle(int pos,T ele); //指定位置新增元素ele
private:
    T data[MAXSIZE]; //順序表首地址
    int cnt; //順序表的有效長度
};
//順序表的無參初始化
template <class T>
SqList<T>::SqList(T a[],int len)
{
    if(len>MAXSIZE)
        cout<<"引數無效"<<endl;
    for(int i =0 ;i<len;i++)
        data[i] = a[i];
    cnt = len;
}

template <class T>
void SqList<T>::showArr()
{
    for(int i=0;i<cnt;i++)
        cout<<data[i]<<" ";
    cout<<endl;
}
template <class T>
bool SqList<T>::isEmpty()
{
    if(cnt == 0)
        return true;
    else
        return false;
}
template <class T>
bool SqList<T>::isFull()
{
    if(cnt == MAXSIZE)
        return true;
    else
        return false;
}
template <class T>
void SqList<T>::appendArr(T ele)
{
    if(isFull())
        cout<<"順序表已經滿了"<<endl;
    else
    {
     data[cnt] = ele;
     cnt++;
    }

}
template <class T>
void SqList<T>::deleteArr(int pos)
{
    if(isEmpty())
        cout<<"順序表為空"<<endl;
    if(pos<1||pos>cnt)
        cout<<"輸入無效"<<endl;
    else
    {
        for(int i=pos;i<cnt;i++)
        {
            data[i-1] = data[i];
        }
        cnt--;
    }
}
template <class T>
T SqList<T>::getArr(int pos)
{
    if(pos<1 || pos>cnt)
    {
        cout<<"位置無效"<<endl;
        return -1;
    }

    else
    {
        return data[pos-1];  //邏輯位置和ele下標相互轉化
    }
}
template <class T>
void SqList<T>:: insertEle(int pos,T ele)
{
    if(isEmpty())
        cout<<"順序表為空"<<endl;
    if(pos<1||pos>cnt)
        cout<<"輸入無效"<<endl;
    else
    {
        for(int i =cnt;i>=pos; i--)
        {
            data[i] = data[i-1];
        }
        data[pos-1] = ele;
        cnt++;
    }
}
int main()
{
    int a[10];
    for(int i=0;i<10;i++)
        a[i]=rand()%100+1;
    SqList<int> arr(a,10);
    arr.showArr();
    arr.appendArr(9);
    arr.appendArr(39);
    arr.showArr();
    arr.deleteArr(12);
    arr.deleteArr(1);
    arr.showArr();
    cout<<arr.getArr(8)<<endl;
    arr.insertEle(10,0);
    arr.insertEle(11,20);
    arr.showArr();
    return 0;
}