資料結構演算法實現-順序表基本操作
阿新 • • 發佈:2019-02-17
資料結構演算法實現
實現了高一凡的<<資料結構>>,書中的程式碼是基於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一些實現檔案並未在主函式呼叫 。
執行結果: