資料結構(1)--線性表順序表的主要操作的實現
阿新 • • 發佈:2019-02-10
參考書籍:資料結構(C語言版) 嚴蔚敏 吳偉民編著 清華大學出版社
1.基本定義
#include<stdio.h>
//順序表:1.使用動態分配的一維陣列
// 2.使用靜態分配的一維陣列
//本例項使用靜態分配
#define LIST_INIT_SIZE 100
typedef int ElemType;
typedef struct SqList{
ElemType data[LIST_INIT_SIZE];
int len;
}SqList;
2.建立線性表和列印輸出線性表
//建立一個長度為n的順序線性表 void createSqList(SqList &L, int n){ printf("請輸入%d個數:\n", n); for(int i = 0; i < n; i++){ scanf("%d",&L.data[i]); } L.len = n; //printSqList(L); }
//列印輸出順序線性表
void printSqList(SqList L){
printf("列印線性表:");
for(int i = 0; i < L.len; i++){
printf("%d ",L.data[i]);
}
printf("\n");
}
演示:
void main(){
//初始化一個空的線性表
SqList L;
L.len=0;
createSqList(L, 5);//建立一個線性表
printSqList(L);
}
3.插入操作
//在第i(1<=i<=n)個元素之前插入一個元素,需要向後移動n-i+1個元素, //在最後插入則不需要移動任何元素,可供插入的位置有n+1個, //從後往前找插入的位置,其中i表示位序,第i個元素的下標i-1,i的範圍是1~n+1 //時間複雜度:O(n) void insertSqList(SqList &L,int i, ElemType e){ if(i>L.len+1||i<1){ printf("插入位置引數不合法"); }else if(L.len >= LIST_INIT_SIZE){ printf("表已滿,無法差插入"); }else{ int j = L.len-1; for(j;j>=i-1;j--){ L.data[j+1] = L.data[j];//從後往前移動元素 } L.data[i-1] = e; L.len++; } }
演示:
void main(){
//初始化一個空的線性表
SqList L;
L.len=0;
createSqList(L, 5);//建立一個線性表
printSqList(L);
//完成插入功能
printf("您要插入的資料和位置(1~%d)(如:在第2個位置插入10則輸入:10,2):",L.len);
int elem, pos;
scanf("%d,%d",&elem,&pos);
insertSqList(L,pos,elem);
printSqList(L);
}
//建立一個線性表實際上也是不斷往一個空表裡插入元素的過程 //所以可利用插入演算法實現線性表的建立 void createUseInsertSqList(SqList &L, int n){ printf("請輸入%d個數:\n", n); int x; for(int i = 0; i < n; i++){ scanf("%d", &x); insertSqList(L,i+1,x); } L.len = n; }
演示:
void main(){
//初始化一個空的線性表
SqList L;
L.len=0;
/*
createSqList(L, 5);//建立一個線性表
printSqList(L);
*/
createUseInsertSqList(L, 5);
printSqList(L);
}
4.刪除操作
//刪除第i(1<=i<=L.len)個元素,並用e返回其值
//時間複雜度:O(n)
void delSqList(SqList &L, int i, ElemType &e){
if(i>L.len||i<1){
printf("刪除位置引數不合法");
}
int j = i-1;//j是要被刪除元素的下標
e = L.data[j];
printf("刪除的第%d位置的資料是%d\n",i,e);
for(j;j<L.len-1;j++){
L.data[j] = L.data[j+1];
}
L.len--;
}
演示:
void main(){
//初始化一個空的線性表
SqList L;
L.len=0;
createSqList(L, 5);//建立一個線性表
printSqList(L);
//完成刪除功能
printf("您要刪除的資料的位置(如:要刪除第2個位置的資料則輸入(1~%d):2):",L.len);
int pos;
ElemType elem;
scanf("%d",&pos);
delSqList(L,pos,elem);
printSqList(L);
}
5.兩個線性表的merge操作
//已知線性表La和Lb中的資料元素按值非遞減排列,現要求將La和Lb歸併為一個新的線性表Lc,且Lc中的資料元素仍然按值非遞減有序排列
//實現:為保持Lc的非遞減有序,則當a<=b時,c=a;當a>b時,c=b
//時間複雜度:O(La.len+Lb.len)
//例項:La=(3,5,8,11),Lb=(2,6,8,9,11,15,20),Lc=(2,3,5,6,8,8,9,11,11,15,20),注意並沒有去重,只是做了合併
void mergeSqList(SqList La, SqList Lb, SqList &Lc){
int i=0, j=0;
Lc.len=La.len+Lb.len;//初始化Lc
int k =0;
while(i<La.len&&j<Lb.len){
if(La.data[i]<=Lb.data[j]){
Lc.data[k]=La.data[i];
i++;
k++;
}else{
Lc.data[k]=Lb.data[j];
j++;
k++;
}
}
while(i<La.len){
Lc.data[k]=La.data[i];
i++;
k++;
}
while(j<Lb.len){
Lc.data[k]=Lb.data[j];
j++;
k++;
}
}
演示:
void main(){
//完成merge操作
SqList La, Lb, Lc;
//初始化線性表
La.len = Lb.len =Lc.len = 0;
printf("建立線性表La:\n");
createSqList(La, 4);//建立線性表La
printSqList(La);
printf("建立線性表Lb:\n");
createSqList(Lb, 7);//建立線性表Lc
printSqList(Lb);
mergeSqList(La, Lb, Lc);
printf("merge以後得到的Lc:");
printSqList(Lc);
}
6.兩個線性表的union操作
//利用兩個線性表La,Lb分別表示兩個集合A和B(線性表中的資料元素即為集合元素),現要求一個新的集合A=AUB
//實現:擴充套件線性表La,即從Lb中依次取得每個資料元素,並依值在La中進行查訪,若在La中不存在則插入之。
//例項:La=(3,5,8,11),Lb=(2,6,8,9,11,15,20),union以後的La=(3,5,8,11,2,6,9,15,20),La.len=9,注意有去重,但不care求並集以後的順序
//時間複雜度:O(La.len * Lb.len)
int locateElem(SqList L, ElemType e){//查詢線性表L中第一個與資料元素e相等(也可以是其他比較方法)的元素的位置(1~L.len),
//若沒找到則返回0,找到則返回位序,時間複雜度:O(L.len)
int i = 1;//i表示位序
while(i<=L.len&&L.data[i-1]!=e){
i++;
}
if(i<=L.len)
return i;
else
return 0;
}
void unionSqList(SqList &La, SqList Lb){
for(int i = 0; i < Lb.len; i++){
ElemType e = Lb.data[i];
if(!locateElem(La, e)){//e在La中不存在//O(La.len)
insertSqList(La,La.len+1, e);//由於總在表尾插入,所以插入操作的時間複雜度與表長無關
}
}
}
演示:
void main(){
//完成union操作
SqList La, Lb;
//初始化線性表
La.len = Lb.len = 0;
printf("建立線性表La:\n");
createSqList(La, 4);//建立線性表La
printSqList(La);
printf("建立線性表Lb:\n");
createSqList(Lb, 7);//建立線性表Lc
printSqList(Lb);
unionSqList(La, Lb);
printSqList(La);
printf("La的長度為%d\n",La.len);
}
注意:將merge第一個迴圈體中以switch語句代替if語句,即分出3種情況,當a=b時,只將兩者之一插入到Lc中,則此時演算法完成的操作和union完全相同,而時間複雜度卻不同,其原因有二:
1.La,Lb中的元素都是依值遞增(同一集合中元素不等),則對Lb中每個元素,不需要再La中從表頭至表尾進行全程搜尋
2.由於用新表Lc表示“並集”,則插入操作實際上藉助“複製”完成,而無須因插入導致移動一系列元素
由此可見,若以線性表表示集合並進行集合的各種運算,應先對錶中的元素進行排序,則可降低集合運算的時間複雜度