数据结构学习笔记:顺序表的删除操作及其演化题目总结
目錄
- 前言
- 例題
- 類(lèi)似題目1
- 類(lèi)似題目2
- 類(lèi)似題目3
- 類(lèi)似題目4
- 類(lèi)似題目5
- 結(jié)語(yǔ)
前言
文章代碼皆在Dev-C++ 5.11中測(cè)試,主要是總結(jié)一些方法,從而總結(jié)一些規(guī)律使自己進(jìn)一步地深化學(xué)習(xí)內(nèi)容,僅供參考,若有代碼錯(cuò)誤或表述不當(dāng)之處,歡迎指正!
例題
例、設(shè)計(jì)一個(gè)刪除算法,刪除順序表L中的第i個(gè)位置的元素,用引用變量返回。
思路:
由于這個(gè)函數(shù)刪除后順序表L有變,所以L(fǎng)前要有&,且我們要返回的變量也是變化的,一開(kāi)始將其初始值設(shè)置為0,所以該變量前面也要加引用。
首先要判斷刪除的元素位置i是否有效,我們知道這里的i是位序(并不是數(shù)組,數(shù)組里面從0開(kāi)始;而位序從1開(kāi)始),所以當(dāng)i小于1且i大于順序表的長(zhǎng)度時(shí)顯示出錯(cuò)信息。
if (i<1||i>L.length)return false;由于我們要?jiǎng)h除某個(gè)元素,并通過(guò)引用變量返回,所以這里先獲得位序?yàn)閕的元素(i-1),并將這個(gè)位置的元素賦值給引用變量,然后這個(gè)位置就空了即被刪除。
e=L.data[i-1];刪除該元素后,我們要將后面的元素都向前移動(dòng)一格,這里注意,我們先移動(dòng)刪除元素右邊的元素,而不從最后一個(gè)元素向前移,即我們可以設(shè)置一個(gè)for循環(huán),將位序i這個(gè)量賦給j,作為j的初始值從而開(kāi)始對(duì)位序?yàn)閕后的元素進(jìn)行向前移一格,按之前說(shuō)的,所以要將數(shù)組下標(biāo)大的賦值給下標(biāo)小的,即
L.data[j-1]=L.data[j];刪除后順序表要減1,并返回true表示刪除成功。
核心代碼如下:
完整代碼如下:
#include<stdio.h> #define MaxSize 10 typedef struct {int data[MaxSize];int length; } SqList;/*初始化順序表*/ void InitList(SqList L) {L.length=0; }/*順序表的輸出,從頭到尾輸出順序表中各元素的值*/ void DispList(SqList L) {for(int i=0; i<L.length; i++)printf("%d ",L.data[i]); }/*順序表的刪除操作 (刪除L中第i個(gè)位置的元素并引用變量e返回)*/ bool ListDelete(SqList &L,int i,int &e) {if (i<1||i>L.length) //在[1,length+1]內(nèi)有效return false; //刪除失敗返回truee=L.data[i-1]; //將要?jiǎng)h除的元素賦值給e,由于是數(shù)組所以要i-1for(int j=i; j<L.length; j++)L.data[j-1]=L.data[j]; //將要?jiǎng)h除的位置,第i個(gè)元素后的元素前移,先移動(dòng)前面的元素,即下標(biāo)大的賦值給下標(biāo)小的L.length--; //數(shù)組的長(zhǎng)度減1return true; //刪除成功后返回true }//主函數(shù) int main() {SqList L;int a;int e=0; //初始化e的值 InitList(L);printf("請(qǐng)輸入建立順序表的元素個(gè)數(shù):\n");scanf("%d",&L.length);printf("請(qǐng)輸入整數(shù):\n");for(int i=0; i<L.length; i++)scanf("%d",&L.data[i]);printf("當(dāng)前順序表為:\n");DispList(L);printf("\n");printf("請(qǐng)輸入想刪除的元素位置:\n",a);scanf("%d",&a);if (ListDelete(L,a,e))printf("已刪除順序表中第%d個(gè)元素,其元素值為%d\n",a,e);elseprintf("輸入的位序i不合法,刪除操作失敗!\n");printf("當(dāng)前順序表為:\n");DispList(L);return 0; }運(yùn)行結(jié)果如下:
類(lèi)似題目1
例、對(duì)長(zhǎng)度為n的順序表L,編寫(xiě)一個(gè)時(shí)間復(fù)雜度為O(n)、空間復(fù)雜度為O(1)的算法,該算法實(shí)現(xiàn)刪除線(xiàn)性表中所有值為x的數(shù)據(jù)元素。
思路:
通過(guò)定義一個(gè)函數(shù)來(lái)實(shí)現(xiàn)要求,其參數(shù)&L是因?yàn)閳?zhí)行刪除操作后,順序表中的元素個(gè)數(shù)會(huì)變化,另外參數(shù)x用于輸入要?jiǎng)h除的數(shù)據(jù)元素。
我們通過(guò)一個(gè)for循環(huán),還是循環(huán)遍歷整個(gè)順序表,設(shè)置兩個(gè)變量i和k,其初始值都為0,目的是找到等于和不等于值為x的數(shù)據(jù)元素,k值用于記錄順序表中不等于x的數(shù)據(jù)元素次數(shù)(這個(gè)次數(shù)最后就可以作為順序表的最終長(zhǎng)度),i用于循環(huán)遍歷順序表,若當(dāng)前的i值不等于x時(shí),則將當(dāng)前數(shù)組下標(biāo)i賦給以k為數(shù)組下標(biāo)的數(shù)據(jù)元素(當(dāng)找到元素時(shí),相當(dāng)于將其后數(shù)據(jù)元素的數(shù)組下標(biāo)i,賦給那個(gè)被找到的數(shù)據(jù)元素,即復(fù)制一個(gè)過(guò)去),且此時(shí)k++;而若等于x時(shí),本次for循環(huán)不執(zhí)行,即本次循環(huán)的k值為順序表中不等于x的數(shù)據(jù)元素次數(shù)。
int k=0; for(int i=0; i<L.length; i++) { //遍歷順序表if(L.data[i]!=x) { //若不等于x,則將當(dāng)前值賦給當(dāng)前值;若不等于則不只需if內(nèi)的語(yǔ)句,k值不變L.data[k]=L.data[i];k++;} }所以最后我們得到的k=總長(zhǎng)度-不等于x的數(shù)據(jù)元素個(gè)數(shù),然后將這個(gè)值賦給L.length從而修改順序表的長(zhǎng)度,后面的元素都被剪除,從而達(dá)到刪除所有值為x的數(shù)據(jù)元素的操作。
L.length=k; //最后將k值賦給順序表的長(zhǎng)度,此時(shí)長(zhǎng)度為除掉所有為x的數(shù)據(jù)元素后的值核心代碼如下:
/*刪除順序表中所有值為x的數(shù)據(jù)元素*/ void del_x(SqList &L,int x) {int k=0; //k用于記錄順序表中不等于x的數(shù)據(jù)元素for(int i=0; i<L.length; i++) { //遍歷順序表if(L.data[i]!=x) { //若不等于x,則將當(dāng)前值賦給當(dāng)前值;若不等于則不只需if內(nèi)的語(yǔ)句,k值不變L.data[k]=L.data[i];k++;}}L.length=k; //最后將k值賦給順序表的長(zhǎng)度,此時(shí)長(zhǎng)度為除掉所有為x的數(shù)據(jù)元素后的值 }這里講得有點(diǎn)繁雜,所以對(duì)代碼進(jìn)行一些修改,……,從而可觀(guān)察每次循環(huán)后的當(dāng)前順序表,根據(jù)結(jié)果可可以更好理解執(zhí)行情況,如下:
第零次循環(huán)(i=0),第一次循環(huán)沒(méi)有找到與x=1相同的元素,所以順序表無(wú)變化,i和k的值正常遞加;第二次循環(huán)(i=3)找到目標(biāo)元素,本次if條件語(yǔ)句下的內(nèi)容不執(zhí)行,k2值不變,此時(shí)數(shù)組下標(biāo)為i3(由于是數(shù)組所以實(shí)際上為i4,后面的i和k都是一樣)的數(shù)據(jù)元素替換數(shù)組下標(biāo)為k2的數(shù)據(jù)元素;第三次循環(huán)正常運(yùn)行,i和k的值正常遞加,k為k3,i為i4;第四次循環(huán)又找到目標(biāo)元素,所以此時(shí)數(shù)組下標(biāo)為i4的數(shù)據(jù)元素替換數(shù)組下標(biāo)為k3的數(shù)據(jù)元素,由于本次循環(huán)正常進(jìn)行所以k值加1,為k4;第五次循環(huán)i=6不滿(mǎn)足i<L.Length退出for循環(huán),將k4的值賦給順序表長(zhǎng)度,后面的元素被剪除。
完整代碼如下:
運(yùn)行結(jié)果如下:
與例題2的相似對(duì)比總結(jié):
類(lèi)似題目2
例、刪除有序順序表中重復(fù)的數(shù)據(jù)元素,使表中所有元素的值均不同。
思路:
這道題要注意輸入的順序表是有序的,通過(guò)for循環(huán)遍歷有序順序表,分別設(shè)置參數(shù)i=0及j=1,從而查找下一個(gè)與上一個(gè)元素值不相同的元素,當(dāng)不相同時(shí),將元素向前移動(dòng),然后j++;若相同則退出本次循環(huán),然后j++,最后得到的所有元素不重復(fù)的值統(tǒng)計(jì)個(gè)數(shù),賦給L.length,此時(shí)i+1前都是不重復(fù)的元素,后面多余的元素即重復(fù)元素,即完成刪除順序表中重復(fù)的數(shù)據(jù)元素。
核心代碼如下:
對(duì)代碼進(jìn)行一些修改,……,從而可觀(guān)察每次循環(huán)后的當(dāng)前順序表,根據(jù)結(jié)果可以更好理解執(zhí)行情況,如下:
完整代碼如下:
運(yùn)行結(jié)果如下:
與例題的類(lèi)似對(duì)比:
類(lèi)似題目3
例、刪除順序表中重復(fù)的數(shù)據(jù)元素,使表中所有元素的值均不同。
【本題代碼參考文章:https://blog.csdn.net/qq_42285148/article/details/117393638】
思路:
這題與題目2相比也就是將有序順序表改為順序表,設(shè)置兩個(gè)for循環(huán),從內(nèi)自外循環(huán)遍歷順序表,內(nèi)層循環(huán)從順序表的第二位元素開(kāi)始,跟上一題類(lèi)似,不過(guò)這里是要查找下一個(gè)與上個(gè)元素值相同的元素,這里再進(jìn)行分支若當(dāng)前查找的下一個(gè)元素至順序表的末尾,則將下一個(gè)元素賦值為0,且順序表的長(zhǎng)度減一;若不是順序表的末尾,則繼續(xù)進(jìn)行一個(gè)for循環(huán),對(duì)其中將下標(biāo)大的元素賦給下標(biāo)小的元素,將元素全部左移,然后再將順序表的長(zhǎng)度減一,最后再j–,繼續(xù)回到兩層for循環(huán),檢查下一個(gè)與上個(gè)元素值相同的元素。
核心代碼如下:
完整代碼如下:
#include<stdio.h> #define MaxSize 10 typedef struct {int data[MaxSize];int length; } SqList;/*初始化順序表*/ void InitList(SqList L) {L.length=0; }/*順序表的輸出,從頭到尾輸出順序表中各元素的值*/ void DispList(SqList L) {for(int i=0; i<L.length; i++)printf("%d ",L.data[i]); }/*刪除順序表中重復(fù)的元素*/ bool Delete_same2(SqList &L) {if(L.length==0)return false;int i,j,k;for(i=0;i<L.length;i++){ //從順序表的第一位數(shù)據(jù)元素遍歷整個(gè)順序表for(j=i+1;j<L.length;j++) //從順序表的第二位數(shù)據(jù)元素遍歷整個(gè)順序表if(L.data[j]==L.data[i]){ //查找下一個(gè)與上個(gè)元素值相同的元素if(j==L.length){ //若下一個(gè)查找的元素到順序表的表尾L.data[j]=0;L.length--;}else{for(k=j;k<L.length;k++) //若下一個(gè)查找的元素還沒(méi)到表尾L.data[k]=L.data[k+1]; //將下標(biāo)大的元素賦給下標(biāo)小的元素L.length--; //順序表的長(zhǎng)度減1}j--;}}return true; }//主函數(shù) int main() {SqList L;InitList(L);printf("請(qǐng)輸入建立順序表的元素個(gè)數(shù):\n");scanf("%d",&L.length);printf("請(qǐng)輸入整數(shù):\n");for(int i=0; i<L.length; i++)scanf("%d",&L.data[i]);printf("當(dāng)前順序表為:\n");DispList(L);printf("\n"); printf("刪除重復(fù)值后的順序表為:\n");Delete_same2(L);DispList(L);return 0; }運(yùn)行結(jié)果如下:
類(lèi)似題目4
例、從順序表中刪除其值在s與t之間的所有元素(包含s和t,且s<t),若s或t不合理或順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行。
思路:
首先判斷s<t且順序表不為空則繼續(xù)執(zhí)行操作。
然后遍歷順序表,在循環(huán)內(nèi),由于我們要?jiǎng)h除值在s-t之間的元素且包括s、t,所以要通過(guò)一個(gè)if條件語(yǔ)句判斷當(dāng)前循環(huán)的data[i]的值在不在這個(gè)范圍內(nèi),若在則將k++(k的初始值為0,該變量用于計(jì)數(shù),計(jì)最后刪除處于范圍中的數(shù)量);而若當(dāng)前數(shù)據(jù)元素不在則將當(dāng)前刪除的位置的第i個(gè)數(shù)組下標(biāo)的元素前移,這里先移下標(biāo)大的元素,再移下標(biāo)小的元素,依次全部向左移。
for(i=0; i<L.length; i++) { //循環(huán)遍歷順序表 if(L.data[i]>=s&&L.data[i]<=t)//當(dāng)數(shù)據(jù)元素值在s與t之間(包括s、t)的所有元素則k++ k++;elseL.data[i-k]=L.data[i]; //將要?jiǎng)h除的位置,第i個(gè)元素后的元素前移,先移動(dòng)前面的元素,即下標(biāo)大的賦值給下標(biāo)小的 }遍歷順序表后,順序表的長(zhǎng)度減k,此時(shí)順序表的長(zhǎng)度為刪除前的長(zhǎng)度-要?jiǎng)h除的元素長(zhǎng)度(k)。
L.length=L.length-k; //順序表L的長(zhǎng)度減k核心代碼如下:
/*刪除其值在s與t之間的所有元素(包含s和t,且s<t),若不合理或順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行*/ bool Del_st(SqList &L,int s,int t) {int i,k=0;if(s>=t||L.length==0) //若不合理或順序表為空,顯示出錯(cuò)信息return false;for(i=0; i<L.length; i++) { //循環(huán)遍歷順序表 if(L.data[i]>=s&&L.data[i]<=t)//當(dāng)數(shù)據(jù)元素值在s與t之間(包括s、t)的所有元素則k++ k++;elseL.data[i-k]=L.data[i]; //將要?jiǎng)h除的位置,第i個(gè)元素后的元素前移,先移動(dòng)前面的元素,即下標(biāo)大的賦值給下標(biāo)小的}L.length=L.length-k; //順序表L的長(zhǎng)度減kreturn true; }完整代碼如下:
#include<stdio.h> #define MaxSize 10 typedef struct {int data[MaxSize];int length; } SqList;/*初始化順序表*/ void InitList(SqList L) {L.length=0; }/*順序表的輸出,從頭到尾輸出順序表中各元素的值*/ void DispList(SqList L) {for(int i=0; i<L.length; i++)printf("%d ",L.data[i]); }/*刪除其值在s與t之間的所有元素(包含s和t,且s<t),若不合理或順序表為空, 則顯示出錯(cuò)信息并退出運(yùn)行*/ bool Del_st(SqList &L,int s,int t) {int i,k=0;if(s>=t||L.length==0) //若不合理或順序表為空,顯示出錯(cuò)信息return false;for(i=0; i<L.length; i++) { //循環(huán)遍歷順序表if(L.data[i]>=s&&L.data[i]<=t)//當(dāng)數(shù)據(jù)元素值在s與t之間(包括s、t)的所有元素則k++k++;elseL.data[i-k]=L.data[i]; //將要?jiǎng)h除的位置,第i個(gè)元素后的元素前移,先移動(dòng)前面的元素,即下標(biāo)大的賦值給下標(biāo)小的}L.length=L.length-k; //順序表L的長(zhǎng)度減kreturn true; }//主函數(shù) int main() {SqList L;int s,t;InitList(L);printf("請(qǐng)輸入建立順序表的元素個(gè)數(shù):\n");scanf("%d",&L.length);printf("請(qǐng)輸入整數(shù):\n");for(int i=0; i<L.length; i++)scanf("%d",&L.data[i]);printf("當(dāng)前順序表為:\n");DispList(L);printf("\n");printf("請(qǐng)輸入要?jiǎng)h除的范圍(s<t):\n");scanf("%d %d",&s,&t);if (Del_st(L,s,t)) {printf("刪除后的順序表為:\n");DispList(L);} elseprintf("操作失敗!\n");return 0; }運(yùn)行結(jié)果如下:
與例題2的相似對(duì)比總結(jié):
類(lèi)似題目5
例、從順序表中刪除具有最小值的元素(假設(shè)唯一)并由函數(shù)返回被刪元素的值。空出的位置由最后一個(gè)元素補(bǔ)齊,若順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行。
思路:
本題較于上面的例題,也是刪除元素,但這是刪除順序表中最小值元素,由于不知道哪個(gè)元素最小,不像例題中直接通過(guò)位序進(jìn)行刪除元素,所以也是要遍歷順序表,首先假設(shè)數(shù)組的第一位元素是最小值元素,即L.data[0],將其賦值給e變量?jī)?chǔ)存,這樣,在for循環(huán)中從數(shù)組的第一位元素開(kāi)始搜索最小值,i的值每次遞加每次搜索目標(biāo)元素,當(dāng)搜索到后,將另外假設(shè)的一個(gè)變量pos為最小元素的下標(biāo)作為后面用,如下:
for循環(huán)中從第二位(i=1)開(kāi)始遍歷搜索順序表中最小值的元素,然后通過(guò)引用變量,將其賦值給它進(jìn)而刪除,如下:
for(int i=1;i<L.length;i++)if(L.data[i]<e){ //找到順序表中最小值的元素 e=L.data[i]; //使其賦值給e,從而刪除這個(gè)值 pos=i; //通過(guò)將i賦值給pos,來(lái)獲取刪除元素位序i對(duì)應(yīng)的數(shù)組下標(biāo) }另外由于題目還要求將刪除的那個(gè)位置的元素用最后一個(gè)元素補(bǔ)齊,我們知道順序表數(shù)組中最后一個(gè)元素為L(zhǎng).data[L.length-1](數(shù)組下標(biāo)從0開(kāi)始),通過(guò)另外設(shè)置一個(gè)變量來(lái)對(duì)刪除的最小值的元素的數(shù)組下標(biāo)位置進(jìn)行記錄,然后與最后一個(gè)元素進(jìn)行交換賦值,如下:
L.data[pos]=L.data[L.length-1]; //刪除的空出位置由最后一個(gè)元素填補(bǔ)核心代碼如下:
/*從順序表中刪除最小值(假設(shè)唯一),并返回該值,且空的位置由 最后一個(gè)元素補(bǔ)齊,若順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行*/ bool Del_Min(SqList &L,int &e){if(L.length==0) //順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行return false;e=L.data[0]; //將數(shù)組的第一位元素賦值給e,從數(shù)組的第一位元素開(kāi)始搜索最小值int pos=0; //假設(shè)pos元素最小,pos初始值為0 for(int i=1;i<L.length;i++)if(L.data[i]<e){ //找到順序表中最小值的元素 e=L.data[i]; //使其賦值給e,從而刪除這個(gè)值 pos=i; //通過(guò)將i賦值給pos,來(lái)獲取刪除元素位序i對(duì)應(yīng)的數(shù)組下標(biāo) } L.data[pos]=L.data[L.length-1]; //刪除的空出位置由最后一個(gè)元素填補(bǔ)L.length--; //順序表的長(zhǎng)度減1return true; }完整代碼如下:
#include<stdio.h> #define MaxSize 10 typedef struct {int data[MaxSize];int length; } SqList;/*初始化順序表*/ void InitList(SqList L) {L.length=0; }/*順序表的輸出,從頭到尾輸出順序表中各元素的值*/ void DispList(SqList L) {for(int i=0; i<L.length; i++)printf("%d ",L.data[i]); }/*從順序表中刪除最小值(假設(shè)唯一),并返回該值,且空的位置由 最后一個(gè)元素補(bǔ)齊,若順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行*/ bool Del_Min(SqList &L,int &e){if(L.length==0) //順序表為空,則顯示出錯(cuò)信息并退出運(yùn)行return false;e=L.data[0]; //將數(shù)組的第一位元素賦值給e,從數(shù)組的第一位元素開(kāi)始搜索最小值int pos=0; //假設(shè)pos元素最小,pos初始值為0 for(int i=1;i<L.length;i++)if(L.data[i]<e){ //找到順序表中最小值的元素 e=L.data[i]; //使其賦值給e,從而刪除這個(gè)值 pos=i; //通過(guò)將i賦值給pos,來(lái)獲取刪除元素位序i對(duì)應(yīng)的數(shù)組下標(biāo) } L.data[pos]=L.data[L.length-1]; //刪除的空出位置由最后一個(gè)元素填補(bǔ)L.length--; //順序表的長(zhǎng)度減1return true; }//主函數(shù) int main() {SqList L;int e=0; //初始化e的值 InitList(L);printf("請(qǐng)輸入建立順序表的元素個(gè)數(shù):\n");scanf("%d",&L.length);printf("請(qǐng)輸入整數(shù):\n");for(int i=0; i<L.length; i++)scanf("%d",&L.data[i]);printf("當(dāng)前順序表為:\n");DispList(L);printf("\n");if (Del_Min(L,e))printf("已刪除順序表中最小值元素,其元素值為%d,且已用最后一個(gè)元素填補(bǔ)!\n",e);elseprintf("順序表為空,操作失敗!\n");printf("當(dāng)前順序表為:\n");DispList(L);return 0; }運(yùn)行結(jié)果如下:
與例題2的相似對(duì)比總結(jié):
結(jié)語(yǔ)
參考書(shū)籍:《王道 數(shù)據(jù)結(jié)構(gòu) 考研復(fù)習(xí)指導(dǎo)》
總結(jié)
以上是生活随笔為你收集整理的数据结构学习笔记:顺序表的删除操作及其演化题目总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (*长期更新)软考网络工程师学习笔记——
- 下一篇: 计算机网络实验(华为eNSP模拟器)——