順序表的創建插入與刪除
坑爹的數據結構課,在加上坑爹的數據結構老師,將來的數據結構之路想必不會順暢吧 。
好吧,閒話不多說。這該死的數據結構課上都沒怎麼聽,哎我以爲我“苦學”一寒假的鏈表,最開始的數據結構應該無壓力吧,tmd沒想到第二週的作業就讓我懵逼了。
好吧一共三個題,第一個是處理矩陣,第二個是計算單詞數,都是小菜一碟。但我看到第三題時:順序表的創建,插入刪除時,我傻眼了。嘛玩意兒!我就去開始翻教材——嚴蔚敏的《數據結構》。用一句話描述我當時的心情就是目瞪口呆。這他媽寫的什麼代碼!排版之亂,還是用僞碼寫的。我雖然學編程不久,但我看無論是美國的《head first》系列還是日本的《征服c指針》,至少給出的代碼是專門給了個區域工工整整的用及佳的代碼風格寫出來的啊。什麼status,Elemtype,這是什麼類型,我怎麼沒聽說過啊!!!於是我上豆瓣看了一下次書的評論,果然是一片罵聲啊。好在暑假自學的時候什麼問題沒遇到過啊。沒怎麼慌,於是上網搜索,然後又把書翻了一遍。哦,原來是要自己定義的。
我再一看老師給出的部分源碼,要自己補充完整的。心裏有事一萬匹草泥馬奔過。這些的什麼啊!拜託變量聲明寫出來好嗎,代碼格式還能不能再亂一點。好吧經過我的刻苦攻關,代碼寫完了:/*構造順序表List(要求順序表存儲空間的初始分配長度爲10,分配增量爲5),在List上實現元素的插入、刪除(提示:參照教材P23-24算法2.3,算法2.4,算法2.5)。具體要求如下:
可以單獨編寫全部代碼完成,也可以在如下代碼裏補充相應代碼完成該實驗任務。
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_INIT_SIZE 10 //線性表存儲空間的初始分配量
#define LISTINCREMENT 5 //線性表存儲空間的分配增量
#define TRUE 1
#define OK 1
#define FALSE 0
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//請編碼完成常量名及自定義數據類型的定義
typedef int status;
typedef int ElemType;
typedef struct{
ElemType *elem; //存儲空間的基地址
int length; //當前線性表的長度
int listsize; //當前分配的存儲容量
}SqList;
void InitList(SqList &l)
{
l.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//動態申請初始內存
if(l.elem==NULL)
{
exit(OVERFLOW);
}
l.length=0;//長度初始化爲零
l.listsize=LIST_INIT_SIZE;//初始化儲存容量
//請編碼完成順序表l的初始化
}
status ListInsert(SqList &l,int i,ElemType e)//i爲插入的位置,e爲其值
{
if (i<1 || i>l.length+1) return -1;
if(l.length>=l.listsize)
{
ElemType *newbase;
newbase=(ElemType *)realloc(l.elem,(l.listsize+LISTINCREMENT)*sizeof(ElemType));
if(newbase==NULL)
{
return -1;
}
l.elem=newbase;
l.listsize+=LISTINCREMENT;//擴大容量聲明
}
ElemType *p,*q;
q=&l.elem[i-1];//下標減一
for(p=&(l.elem[l.length-1]);p>=q;--p)
{
*(p+1)=*p;
}//將i位置後的所有元素往後移一位
*q=e;
++l.length;
return OK;
}
status ListDelete(SqList &l,int i,ElemType &e)
{
if(i>l.length||i<1)
{
return ERROR;
}
ElemType *p,*q;
p=&l.elem[i-1];
e=*p;//取得要刪除的元素的地址
q=&l.elem[l.length-1];//取得最後一個元素、
while(p<q)
{
*p=*(p+1);
p++;
}
l.length--;
return 0;
//請編碼完成刪除順序表l的第i個數據元素,並將刪除元素值通過參數e返回。如果成功函數返回OK,否則返回ERROR。
}
int main()
{
SqList List;
int e;
int i,j;
//初始化順序表
printf("************初始化順序表********************\n");
InitList(List);
printf("初始化List後:List.length=%d List.listsize=%d\n",List.length,List.listsize);
//在表頭依次插入1~10
printf("\n**********在表頭依次插入1~10***************\n");
for (i=1;i<=10;i++)
ListInsert(List,1,i);
printf("在List的表頭依次插入1~10後,表中的數據元素值爲:");
for (i=1;i<=List.length;i++)
printf("%d ",List.elem[i-1]);
printf("\n");
printf("List.length=%d List.listsize=%d\n",List.length,List.listsize);
//繼續在表尾插入第11個元素值:11
printf("\n*********繼續在表尾插入第11個元素值:11*************\n");
ListInsert(List,List.length+1,11);
printf("在表尾插入11後,表中的數據元素值爲:");
for (i=1;i<=List.length;i++)
printf("%d ",List.elem[i-1]);
printf("\n");
printf("List.length=%d List.listsize=%d\n",List.length,List.listsize);
//依次刪除表中第12,11個元素和第10個元素
printf("\n************依次刪除表中第12,11,10個元素*********\n");
for (i=12;i>=10;i--){
j=ListDelete(List,i,e);
if (j==e)
printf("刪除第%d個元素失敗\n",i);
else
printf("刪除第%d個元素成功,其值爲:%d\n",i,e);
}
printf("List.length=%d List.listsize=%d\n",List.length,List.listsize);
return 0;
}
一開始我還以爲順序表就是鏈表,後來才發現不是,比鏈表要簡單,他是在結構體裏創建一個數組,兩個int 變量分別記錄數組長度,當前內寸大小。
插入的邏輯是這樣的:
1.判斷要插入的位置是否合法。(小於1或大於lenth)
2.判斷數組長度有沒有到內存容量極限,若容量滿後應用realloc函數擴大。
3.定義兩個指針,一個指向要插入的位置,一個指向最後一個。
4.從最後一個元素開始用*(p+1)=*p,依次移動。
5.將值賦給對應的位置。
6.lenth++.
刪除的邏輯要簡單點,但我當時犯了個毛病for (i=12;i>=10;i--){
j=ListDelete(List,i,e);
if (j==e)
printf("刪除第%d個元素失敗\n",i);
else
printf("刪除第%d個元素成功,其值爲:%d\n",i,e);
}
這片代碼,我當時糾結於e從哪裏來,沒有賦值啊。後來看到函數原型才知道,e是傳地址進函數的,e在函數裏賦值。
邏輯:
1.判斷要插入的位置是否合法。
2.聲明兩個指針,一個指向刪除元素的地址,一個指向末地址用來做結束循環的標誌。
3.用將要被刪除的值保存進e中
4.*p=*(p+1)
5.lenth--。
基本邏輯就是這樣的。