1. 程式人生 > >資料結構(1)--線性表順序表的主要操作的實現

資料結構(1)--線性表順序表的主要操作的實現

參考書籍:資料結構(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表示“並集”,則插入操作實際上藉助“複製”完成,而無須因插入導致移動一系列元素
由此可見,若以線性表表示集合並進行集合的各種運算,應先對錶中的元素進行排序,則可降低集合運算的時間複雜度