C語言-數據結構-線性表
最近在學習自考課程中的《數據結構》,課程代碼爲02331,使用的教程是2012年版的(主編:蘇仕華)。一開始學習時,有些困難,因爲我沒學習過C,教材中的算法雖然能理解,但不能完全吃透。
所以,又轉去惡補C的基礎知識,如:數組,指針,結構體,宏定義,typedef…等等。
現在回來了,再看這些算法容易多了,自己將“順序表”的基本運算補充實現了,貼上來,給有相同經歷的考生一點點幫助。
1. 線性表的基本運算
對於線性表,常見的基本運算有幾下幾種:
(1)置空表 InitList(L),構造一個空的線性表L.
(2)求表長 ListLength(L),返回線性表L中元素個數,即表長。
(3)取表中第 i 個元素 GetNode(L , x) ,若 1<= i <= ListLength(L),則返回第 i 個元素 ai。
(4)按值查找 LocateNode(L, x),在表 L 中查找第一個值爲 x 的元素,並返回該元素在表 L 中的位置,若表中沒有元素的值爲 x ,則返回值。
(5)插入 InsertList(L , i , x ),在表 L 的第 i 元素之前插入一個值爲 x 的元素,表 L 的長度加 1。
(6)刪除 DeleteList(L , i ),刪除表 L 的第 i 個元素,表 L 的長度減 1 。
上述運算公公是線性表的基本運算,不是其全部運算。因爲不同問題的線性表,所需要的運算可能不同。因此,對於初階問題中涉及其他更爲複雜的運算,可用基本運算的組合來實現。
2. 線性表的存儲結構
線性表的兩種存儲結構有:
(1)線性表的順序結構:指的是將線性表的數據元素按其邏輯次序依次存入一組地址連續的存儲單元裏,用這種方法存儲的線性表稱爲順序表。
(2)線性表的鏈式存儲結構:在使用鏈式存儲結構表示每個數據元素 ai 時,除了存儲 ai 本身的信息之外,還需要一個存儲指示其後繼元素 ai+1存儲位置的指針,這兩個部分組成元素 ai 的存儲映像通常稱爲結點。它包括兩個域:存儲數據元素的域稱爲數據域,存儲直接後繼存儲地址的域稱爲指針域,利用這種存儲方式表示稱爲鏈表。
2.1 順序表的基本運算實現
#include <stdlib.h>
#include <stdio.h>
#define ListSize 100
typedef int DataType; //
/// 定義一個順序表結構體,包含兩個屬性,即數據數組和數據長度
typedef struct {
DataType data[ListSize];
int length;
}SeqList;
/// (1)置空表,構造一個空的線性表L
void InitList(SeqList *L){
L->length = 0;
}
/// (2)求表長,返回線性表的元素個數,即表長
int ListLength(SeqList *L){
return L->length;
}
/// (3)取表中第i個元素,若1<= i <=ListLength(L),則返回第i個元素ai
DataType GetNode(SeqList *L,int i){
return L->data[i-1];
}
/// (4)按值查找,在表L中查找第一個值爲x的元素,並返回該元素在表L中的位置,若表中沒有元素的值爲x,則返回0
int LocateNode(SeqList *L,DataType x){
int res = 0;
for(int i=1;i<=ListLength(L);i++){
if(GetNode(L,i)==x){
res = i;
break;
}
}
return res;
}
/// (5)插入元素,在順序表L中第i個位置之前插入一個新元素x
void InsertList(SeqList *L,int i,DataType x){
int j;
// 如果要插入的位置<1或者>最大索引,則打印位置錯誤,並退出
if(i<1 || i>L->length+1){
printf("d%position error");
return;
}
if(L->length >= ListSize){
printf("overflow");
return;
}
// 將第i個位置及其後面位置上的元素都後稱一位
for(j=L->length-1;j>=i-1;j--){
L->data[j+1]=L->data[j]; // 從最後一個元素開始逐一後移
}
L->data[i-1]=x; // 插入新元素x
L->length++;
}
///順序表的刪除運算(刪除順序表L中第i個位置的元素,並返回被刪除的元素)
DataType DeleteList(SeqList *L,int i){
int j;
DataType x; // DataType是一個通用類型的標識符,在使用時再定義實際類型
if(i<1 || i>L->length){
printf("d%position error");
// exit(0); // 出錯退出處理
}
x = L->data[i]; // 保存被刪除元素
for(j=i;j<L->length;j++){
L->data[j-1]=L->data[j]; // 元素前移
}
L->length--;
return x;
}
/// (6)輸出順序表中的元素
void displayList(SeqList *L){
for(int i=0;i<L->length;i++){
printf("第 %d 項 : 下標=%d,值=%d \n",i+1,i,L->data[i]);
}
printf("\n");
printf("共有元素:%d\n",ListLength(L));
}
/// 輸出第i項節點的值
void printNode(SeqList *L,int i){
printf("第 %d 項 : 下標=%d,值=%d \n",i,i-1,GetNode(L,i));
}
/// 測試各運算函數
int main(){
SeqList list;
SeqList *plist = &list;
InitList(plist);
// 下面是測試InsertList函數
printf("=================================================下面是測試InsertList函數================================\n");
int listSize,listOne;
printf("請輸入你要插入的第一個元素值:\n");
scanf("%d",&listOne);
printf("請輸入你要插入幾個元素值:\n");
scanf("%d",&listSize);
for(int i=1;i<=listSize;i++){
InsertList(plist,i,i+listOne-1);
}
printf("你的順序表中元素如下:\n");
displayList(plist);
// 下面測試DeleteList
printf("=================================================下面測試DeleteList================================\n");
int delI,deleteflag;
printf("是否要刪除某一項(0:否,1:是):\n");
scanf("%d",&deleteflag);
if(deleteflag==1){
while(deleteflag==1){
printf("請輸入你要刪除的項數:\n");
scanf("%d",&delI);
DeleteList(plist,delI);
printf("是否繼續(0:否,1:是):\n");
scanf("%d",&deleteflag);
}
}
printf("刪除操作結束,請查看最終的順序表:\n");
displayList(plist);
// 下面是測試LocateNode函數
printf("=================================================下面是測試LocateNode================================\n");
DataType searchE=11;
while(searchE<100){
int localeRes = LocateNode(plist,searchE);
printf("%d 元素的位置是:%d\n",searchE,localeRes);
printf("請輸入你要查找的元素:\n");
scanf("%d",&searchE);
}
return 0;
}