1. 程式人生 > >資料結構演算法實現-順序表基本操作

資料結構演算法實現-順序表基本操作

資料結構演算法實現

實現了高一凡的<<資料結構>>,書中的程式碼是基於VC6++ c++語言實現的,網上也可以找到TC版的c語言實現的原始碼,TC版的原始碼平臺是 Turbo C 2.0 ,編譯軟體相對較早,因此將採用CodeBlock實現資料涉及的演算法原理,在程式碼順序和標頭檔案宣告,和.c檔案實現上有一些順序上的些許調整:

  • 動態分配建立順序表
  • 賦值操作
  • 插入操作
  • 打印表的內容
  • 求線性表的長度
  • 將所有線上性表Lb中但不在La中的資料元素插入到La中
  • **

c1.h

可以看做是一個總的用於宣告函式型別和定義結構體的標頭檔案,後面大多數實現需要包含c1.h

#include <string.h>
 #include <ctype.h>
 #include <malloc.h> //malloc()等
 #include <limits.h> // INT_MAX等 
 #include <stdio.h> // EOF(=^Z或F6)
 #include <stdlib.h> // atoi()
 #include <io.h> // eof()
 #include <math.h> //floor(),ceil(),abs() 
 #include <process.h> // exit()
/* 函式結果狀態程式碼 */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 // #define OVERFLOW -2 因為在math.h中已定義OVERFLOW的值為3,故去掉此行 typedef int Status; //Status是函式的型別,其值是函式結果狀態程式碼 //typedef int Boolean; // Boolean是布林型別,其值是TRUE或FALSE typedef int ElemType;//定義順序表資料型別為整型

c2_1.h

#ifndef C2_1_H_INCLUDED
#define C2_1_H_INCLUDED /* c2-1.h 線性表的動態分配順序儲存結構 */ #define LIST_INIT_SIZE 10 //線性表儲存空間的初始分配量 #define LIST_INCREMENT 2 // 線性表儲存空間的分配增量 typedef struct _sqlist //定義順序表的結構 { int *elem; // 儲存空間基址 int length; // 當前長度 int listsize; // 當前分配的儲存容量(以sizeof(ElemType)為單位) }SqList; /*下面是順序表操作得函式宣告,定義函式型別,涉及的引數以及返回值*/ Status ListEmpty(SqList L); int ListLength(SqList L); Status GetElem(SqList L,ElemType i,ElemType *e); int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)); Status PriorElem(SqList L,ElemType cur_e,ElemType *pre_e); Status NextElem(SqList L,ElemType cur_e,ElemType *next_e); void DestroyList(SqList *L);//銷燬熟悉怒表 void ClearList(SqList *L);//清空順序表 Status ListInsert(SqList *L,int i,ElemType e); //插入元素 Status ListDelete(SqList *L,ElemType i,ElemType *e);//刪除元素 void ListTraverse(SqList L,void(*vi)(ElemType*)); Status equal(ElemType c1,ElemType c2); int comp(ElemType a,ElemType b); void print(ElemType c); void print2(ElemType c); void print1(ElemType *c); void dbl(ElemType *c); void Union(SqList *la,SqList Lb);//合併元素 Status sq(ElemType c1,ElemType c2); Status equal(ElemType c1,ElemType c2); #endif // C2_1_H_INCLUDED

上面這些函式宣告包含了順序表的一些基本操作,建立,插入,刪除,清空,等等.

bo2-1.c 函式實現

 /* bo2-1.c 順序表示的線性表(儲存結構由c2-1.h定義)的基本操作(12個) */
#include "c1.h"
#include "c2_1.h"
#include <stdio.h>
#include <stdlib.h>

/* 操作結果:構造一個空的順序線性表L */
 void InitList(SqList *L) 
 { 
   (*L).elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
   if(!(*L).elem)
     exit(OVERFLOW); // 儲存分配失敗 
   (*L).length=0; // 空表長度為0 
   (*L).listsize=LIST_INIT_SIZE; // 初始儲存容量 
 }

  /*初始條件:順序線性表L已存在。操作結果:銷燬順序線性表L */
 void DestroyList(SqList *L)
 {
   free((*L).elem);
   (*L).elem=NULL;
   (*L).length=0;
   (*L).listsize=0;
 }

 /* 初始條件:順序線性表L已存在。操作結果:將L重置為空表 */
 void ClearList(SqList *L)
 { 
   (*L).length=0;
 }

 /* 初始條件:順序線性表L已存在。操作結果:若L為空表,則返回TRUE,否則返回FALSE */
 Status ListEmpty(SqList L)
 { 
   if(L.length==0)
     return TRUE;
   else
     return FALSE;
 }

 /* 初始條件:順序線性表L已存在。操作結果:返回L中資料元素個數 */
 int ListLength(SqList L)
 {
   return L.length;
 }

/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L)。操作結果:用e返回L中第i個數據元素的值 */
 Status GetElem(SqList L,ElemType i,ElemType *e)
 { 
   if(i<1||i>L.length)
     return ERROR;
   *e=*(L.elem+i-1);
   return OK;
 }

  /* 初始條件:順序線性表L已存在,compare()是資料元素判定函式(滿足為1,否則為0) 
     操作結果:返回L中第1個與e滿足關係compare()的資料元素的位序。
            若這樣的資料元素不存在,則返回值為0*/
 int LocateElem(SqList L,int e,Status(*compare)(int,int))
 {
   int *p;
   int i=1; /* i的初值為第1個元素的位序 */
   p=L.elem; /* p的初值為第1個元素的儲存位置 */
   while(i<=L.length&&!compare(*p++,e))
     ++i;
   if(i<=L.length)
     return i;
   else
     return 0;
 }

 /* 初始條件:順序線性表L已存在
    操作結果:若cur_e是L的資料元素,且不是第一個,則用pre_e返回它的前驅, 
             否則操作失敗,pre_e無定義 */
 Status PriorElem(SqList L,int cur_e,int *pre_e)
 { 
   int i=2;
   int *p=L.elem+1;
   while(i<=L.length&&*p!=cur_e)
   {
     p++;
     i++;
   }
   if(i>L.length)
     return INFEASIBLE; /* 操作失敗 */
   else
   {
     *pre_e=*--p;
     return OK;
   }
 }

  /* 初始條件:順序線性表L已存在 
   操作結果:若cur_e是L的資料元素,且不是最後一個,則用next_e返回它的後繼, 
         否則操作失敗,next_e無定義 */

 Status NextElem(SqList L,ElemType cur_e,ElemType *next_e)
 {
   int i=1;
   ElemType *p=L.elem;
   while(i<L.length&&*p!=cur_e)
   {
     i++;
     p++;
   }
   if(i==L.length)
     return INFEASIBLE; //操作失敗
   else
   {
     *next_e=*++p;
     return OK;
   }
 }

 //插入操作
 Status ListInsert(SqList *L,int i,ElemType e)
 {
   ElemType *newbase,*q,*p;
   if(i<1||i>(*L).length+1) //i值不合法 
     return ERROR;
   if((*L).length>=(*L).listsize) // 當前儲存空間已滿,增加分配 
   {
     newbase=(ElemType *)realloc((*L).elem,((*L).listsize+LIST_INCREMENT)*sizeof(ElemType));
     if(!newbase)
       exit(OVERFLOW); // 儲存分配失敗
     (*L).elem=newbase; // 新基址 
     (*L).listsize+=LIST_INCREMENT; // 增加儲存容量
   }
   q=(*L).elem+i-1; // q為插入位置
   for(p=(*L).elem+(*L).length-1;p>=q;--p) //插入位置及之後的元素右移 
     *(p+1)=*p;
   *q=e; // 插入e
   ++(*L).length; //表長增1
   return OK;
 }

 //刪除操作
 /* 初始條件:順序線性表L已存在,1≤i≤ListLength(L)
 操作結果:刪除L的第i個數據元素,並用e返回其值,L的長度減1 */
 Status ListDelete(SqList *L,ElemType i,ElemType *e)
 { 
   ElemType *p,*q;
   if(i<1||i>(*L).length) // i值不合法
     return ERROR;
   p=(*L).elem+i-1; // p為被刪除元素的位置
   *e=*p; //被刪除元素的值賦給e
   q=(*L).elem+(*L).length-1; //表尾元素的位置
   for(++p;p<=q;++p) // 被刪除元素之後的元素左移
     *(p-1)=*p;
   (*L).length--; // 表長減1 
   return OK;
 }


 /* 初始條件:順序線性表L已存在
操作結果:依次對L的每個資料元素呼叫函式vi() 
vi()的形參加'&',表明可通過呼叫vi()改變元素的值 */
 void ListTraverse(SqList L,void(*vi)(ElemType*))
 { 
  ElemType *p;
   int i;
   p=L.elem;
   for(i=1;i<=L.length;i++)
     vi(p++);
   printf("\n");
 }

 Status equal(ElemType c1,ElemType c2)
 {
     if(c1==c2)
        return TRUE;
     else
        return FALSE;
 }

 int comp(ElemType a,ElemType b)
 {
     if(a==b)
     return 0;
     else
        return (a-b)/abs(a-b);
 }

 void print(ElemType c)
 {
     printf("%d",c);
 }

 void print2(ElemType c)
 {
     printf("%c",c);
 }

 void print1(ElemType *c)
 {
     printf("%d",*c);
 }

 Status sq(ElemType c1,ElemType c2)
{
    if(c1==c2*c2)
        return TRUE;
        else
            return ERROR;
}

 void dbl(ElemType *c)
 { /* ListTraverse()呼叫的另一函式(元素值加倍) */
   *c*=2;
 }


 void Union(SqList *La,SqList Lb)
{
    //將所有線上性表Lb中但不在La中的資料元素插入到La中
    ElemType e;
    int La_Len,Lb_Len;
    int i;
    La_Len=ListLength(*La);//求線性表的長度
    Lb_Len=ListLength(Lb);
    for(i=1;i<=Lb_Len;i++)
    {
        GetElem(Lb,i,&e);//取Lb中第i個數據元素賦給e
        if(!LocateElem(*La,e,equal))
            ListInsert(La,++La_Len,e);
        }
    }


主函式 main.c

#include <stdio.h>
#include <stdlib.h>
#include  "c1.h"
#include "c2_1.h"

 void main()
 {
   SqList La,Lb;
   int j;
   InitList(&La);//建立空表La
   for(j=1;j<=5;j++)
    ListInsert(&La,j,j);//在La插入元素
    printf("La=  ");
    ListTraverse(La,print1);
    InitList(&Lb);//建立空表Lb
    for(j=1;j<=5;j++)
            ListInsert(&Lb,j,2*j);//在Lb插入元素
      printf("Lb=  ");
    ListTraverse(Lb,print1);
    Union(&La,Lb);//合併順序表
    printf("new La=");
    ListTraverse(La,print1);
 }

主函式主要實現建立兩個順序表,並將兩個順序表合併,在bo2-1.c一些實現檔案並未在主函式呼叫

這裡寫圖片描述

執行結果:

這裡寫圖片描述