天勤2022数据结构(一)线性表
天勤2022數(shù)據(jù)結(jié)構(gòu)(一)線性表
- 前言
- 一、基礎(chǔ)題
- 二、思考題
- 三、真題精選
- 總結(jié)
前言
提示:全文為作者手打,僅供個(gè)人復(fù)習(xí)使用
#define maxSize 50順序表 typedef struct {int data[maxSize];int length; }Sqlist; 單鏈表 typedef struct LNode{int data;struct LNode *next; }LNode;雙鏈表 typedef struct DNode{int data;struct DNode *prev;struct DNode *next; }DNode;一、基礎(chǔ)題
線性表可用順序表和鏈表存儲(chǔ),試問:
-
如果有n個(gè)表同時(shí)并存,并且在處理過程中各表的長度會(huì)動(dòng)態(tài)發(fā)生變化,表的總數(shù)也可能自動(dòng)改變,在此情況下,應(yīng)選用哪種存儲(chǔ)表示?為什么?
用鏈表。
如果采用順序表,在多個(gè)表并存的情況下,一旦發(fā)現(xiàn)某個(gè)表有存滿并溢出的情況,需要移動(dòng)其他表來騰出空間為其擴(kuò)容,導(dǎo)致不斷把大片數(shù)據(jù)反復(fù)移動(dòng)。時(shí)間開銷太大且操作易出錯(cuò)。
若表的總數(shù)還要變化,則會(huì)帶來在不影響其他表工作的情況下開辟新表空間或釋放舊表空間的操作上的麻煩。
采用鏈表就沒有這些問題
內(nèi)存空間足夠情況下,各表的空間分配或釋放不受其他表的影響。 -
若表的總數(shù)基本穩(wěn)定,且很少進(jìn)行插入和刪除但要求以最快的速度存取表中的元素,這時(shí)用哪種存儲(chǔ)表示?為什么?
用順序表、
順序表插入,刪除操作時(shí)間復(fù)雜度為O(n),存取操作時(shí)間復(fù)雜度為O(1)
充分發(fā)揮存取速度塊、存儲(chǔ)利用率高的特點(diǎn)
為什么在單循環(huán)鏈表中設(shè)置尾指針比設(shè)置頭指針更好?
what:尾指針是指向終端結(jié)點(diǎn)的指針
why:使得查找鏈表的開始結(jié)點(diǎn)和終端結(jié)點(diǎn)的時(shí)間復(fù)雜度為O(1)
而設(shè)置頭指針,查找終端結(jié)點(diǎn)的時(shí)間復(fù)雜度仍是O(n)
設(shè)計(jì)一個(gè)算法,將順序表中的所有元素逆置。
void swap(int *a, int *b){int t = *a;*a = *b;*b = t; } void reverse(int *nums, int n){for(int i=0, j=n-1; i<j; i++, j--){myswap(&nums[i], &nums[j]);} }void reverse(Sqlist &L){int i, j;int temp;for(i=0, j=L.length-1; i<j; ++i, --j){temp=L.data[i];L.data[i]=L.data[j];L.data[j]=temp;} }
設(shè)計(jì)一個(gè)算法,從一給定的順序表L中刪除下標(biāo)i~j(i≤j,包括i、j)的所有元素,假定i、j都是合法的
void delete(Sqlist &L, int i, int j){int k, delta;delta=j-i+1;for(k=j+1; k<L.length; k++){L.data[k-delta]=L.data[k];}L.length-=delta; }L.length -= delta;
有一個(gè)順序表L,其元素為整型數(shù)據(jù),設(shè)計(jì)一個(gè)算法,將L中所有小于表頭元素的整數(shù)放在前半部分,大于表頭元素的整數(shù)放在后半部分
void move(Sqlist &L){int temp=L.data[i], i=0, j=L.length-1;while(i<j){while(i<j && L.data[j]>temp)j--;if(i<j){L.data[i]=L.data[j];i++;}while(i<j && L.data[i]<temp)i++;if(i<j){L.data[j] = L.data[i];j--;}}L.data[i] = temp; }有一個(gè)遞增非空單鏈表,設(shè)計(jì)一個(gè)算法刪除值域重復(fù)的結(jié)點(diǎn)。例如,{1,1,2,3,3,3,4,4,7,7,7,9,9,9}經(jīng)過刪除后變成(1,2,3,4,7,9}
void delete(LNode *L){LNode *p=L->next, *q;while(p->next != NULL){if(p->data == p->next->data){q = p->next;p->next = q->next;free(q);}else{p = p->next; }} }設(shè)計(jì)一個(gè)算法刪除單鏈表L(有頭結(jié)點(diǎn))中的一個(gè)最小值結(jié)點(diǎn)
void delete(LNode *L){LNode *pre=L, *p=pre->next, *minp=p, *minpre=pre;while(p != NULL){if(p->data<minp->data){min = p;minpre = pre; }pre = p;p = p->next; }minpre->next = minp->next;free(minp); }有一個(gè)線性表,采用帶頭結(jié)點(diǎn)的單鏈表L來存儲(chǔ)。設(shè)計(jì)一個(gè)算法將其逆置。要求不能建立新結(jié)點(diǎn),只能通過表中已有結(jié)點(diǎn)的重新組合來完成。
void reverse(LNode *L){LNode *p=L->next , *q;L->next=NULL;while(p != NULL){q = p->next;p->next = L->next;L->next = p;p = q;} }設(shè)計(jì)一個(gè)算法,將一個(gè)頭結(jié)點(diǎn)為A的單鏈表(數(shù)據(jù)域?yàn)檎麛?shù))分解成兩個(gè)單鏈表A和B,得A鏈表只含有原來鏈表中data域?yàn)槠鏀?shù)的結(jié)點(diǎn),而B鏈表只含有原鏈表中data域?yàn)榕紨?shù)的結(jié)點(diǎn),且保持原來的相對順序。
void divide(LNode *A, LNode *&B){LNode *p = A, *q;B = (LNode*)malloc(sizeof(LNode));B->next = NULL;q = B;while(p->next!=NULL){if(p->next->data % 2 == 0){q->next = p->next;q = q->next;p->next = p->next->next;}elsep = p->next;}q->next = NULL; }二、思考題
有N個(gè)個(gè)位正整數(shù)存放在int型數(shù)組A[0,…,N-1]中,N為已定義的常量且N≤9,數(shù)組A[]的長度為N,另給一個(gè)int型變量i,要求只用上述變量(A[0]~A[N-1]與i,這N+1個(gè)整型變量)寫一個(gè)算法,找出這N個(gè)整數(shù)中的最小者,并且要求不能破壞數(shù)組A[]中的數(shù)據(jù)。
void getMin(int[] nums, N){int i = nums[0];for(int j = 1; j<N; j++){if(nums[j]<i) i = nums[j];} }寫一個(gè)函數(shù),逆序打印單鏈表中的數(shù)據(jù),假設(shè)指針L指向了單鏈表的開始結(jié)點(diǎn)
dfs(L); void dfs(LNode *node){if(node == NULL)return;dfs(node->next);printf(node->data); }設(shè)有兩個(gè)用有序鏈表表示的集合A和B,設(shè)計(jì)一個(gè)算法,判斷它們是否相等
int equal(Sqlist &A, Sqlist &B){if(A.length != B.length) return -1;for(int i = 0; i<A.length; i++){if(A.data[i]!=B.data[i])return -1;}return 1; }設(shè)A=(a1,a2,…,am)和B=(b1,b2,…,bn)均為順序表,A’和B’分別是除去最大公共前綴后的子表。例如,A=(b,e,i,j,i,n,g),B=(b,e,i,f,a,n,g),則兩者的最大公共前綴為b、e、i,在兩個(gè)順序表中除去最大公共前綴后的子表分別為A’=(j,i,n,g),B’=(f,a,n,g)若A’=B’=空表,則A=B。若A’=空表且B’≠空表,或兩者均不為空且A’的第一個(gè)元素值小于B’的第一個(gè)元素值,則A<B,否則A>B。所有表中元素均為 float型,試編寫一個(gè)函數(shù),根據(jù)上述方法比較A和B的大小。
void compare(){}鍵盤輸入n個(gè)英文字母,輸入格式為n、cl、c2、…、cn,其中n表示字母的個(gè)數(shù)。請編程用這些輸入數(shù)據(jù)建立一個(gè)單鏈表,并要求將字母不重復(fù)地存入鏈表。
LNode *insert(int n){char dic[26] = {0};LNode *L = (LNode*)malloc(sizeof(LNode));L->next = NULL;LNode *p = L, *q;for(int i = 0; i<n; i++){char cur;scanf("%c", &cur);if(dic[cur-'0']==0){dic[cur-'0']=1;q = (LNode*)malloc(sizeof(LNode));q->data = cur;p->next = q;p = p->next;}}return L; }三、真題精選
已知一個(gè)帶有表頭結(jié)點(diǎn)的單鏈表,結(jié)點(diǎn)結(jié)構(gòu)為:
假設(shè)該鏈表只給出了頭指針head。在不改變鏈表的前提下,請?jiān)O(shè)計(jì)一個(gè)盡可能高效的算法,查找鏈表中倒數(shù)第k(k為正整數(shù))個(gè)位置上的結(jié)點(diǎn)。若查找成功,算法輸出該結(jié)點(diǎn)的data值,并返回1;否則,只返回0.
要求:
(1)描述算法的基本設(shè)計(jì)思想。
(2)描述算法的詳細(xì)實(shí)現(xiàn)步驟。
(3)根據(jù)設(shè)計(jì)思想和實(shí)現(xiàn)步驟,采用程序設(shè)計(jì)語言描述算法(使用C或C++語言實(shí)現(xiàn)),關(guān)鍵之處請給出簡要注釋。
基本設(shè)計(jì)思想:
- 從頭至尾遍歷單鏈表,并用指針pre指向當(dāng)前結(jié)點(diǎn)的前k個(gè)結(jié)點(diǎn)。
- 當(dāng)遍歷到鏈表的最后一個(gè)結(jié)點(diǎn)時(shí),指針pre所指向的結(jié)點(diǎn)即為所查找的結(jié)點(diǎn)
詳細(xì)實(shí)現(xiàn)步驟:
- 聲明2個(gè)指針變量cur,pre,1個(gè)整型變量cnt
- 從鏈表頭向后遍歷,指針cur指向當(dāng)前遍歷的結(jié)點(diǎn),結(jié)點(diǎn)pre指向cur所指結(jié)點(diǎn)的前k個(gè)結(jié)點(diǎn),如果cur之前沒有k個(gè)結(jié)點(diǎn),那么pre指向表頭結(jié)點(diǎn)。
- 用整型變量cnt表示當(dāng)前遍歷了多少個(gè)結(jié)點(diǎn),當(dāng)cnt>k時(shí),指針pre隨著每次遍歷也向后移動(dòng)一個(gè)結(jié)點(diǎn)。
- 當(dāng)遍歷完成時(shí),pre要么指向表頭指針,要么指向鏈表中倒數(shù)第k個(gè)位置上的結(jié)點(diǎn)
程序設(shè)計(jì)語言描述:
int find(LNode *L, int k){LNode cur = L, pre = L;int cnt = 0;while(cur != NULL){cur = cur->next;cnt++;/*if判斷不能放前面*/if(cnt > k){pre = pre->next;}}if(cur == L ){return 0;}else{printf("%d", pre->data);return 1;} }設(shè)將n(n>1)個(gè)整數(shù)存放到一維數(shù)組R中。設(shè)計(jì)一個(gè)在時(shí)間和空間兩方面盡可能高效的算法。將R中保存的序列循環(huán)左移P(0<P<n)個(gè)位置,即將R中的數(shù)據(jù)由(X0,X1,…,Xn-1)變換為(Xp,Xp+1,…,Xn-1,X0,X1,…,Xp-1)。要求
(1)給出算法的基本設(shè)計(jì)思想。
(2)根據(jù)設(shè)計(jì)思想,采用C或C++語言描述算法關(guān)鍵之處給出注釋。
(3)說明你所設(shè)計(jì)的算法的時(shí)間復(fù)雜度和空間復(fù)雜度。
基本設(shè)計(jì)思想:
void swap(int[] R, int i, int j){R[i] = R[i]^R[j];R[j] = R[i]^R[j];R[i] = R[i]^R[j]; }void reverse(int[] R, int i, int j){for(; i<j; i++, j--){swap(R, i, j);} }void solution(int[] R, int n, int p){reverse(0, p-1);reverse(p, n-1);reverse(0, n-1); }
時(shí)間復(fù)雜度:O(n)
空間復(fù)雜度:O(1)
3. 已知一個(gè)整數(shù)序列A=(a0,a1,…,an-1),其中0≤ai<n(0≤i<n)若存在ap1=ap2=…=apm=x且m>n/2(0≤pk≤n, 1≤k≤m),則稱x為A的主元素,例如,A=(0,5,5,3,5,7,5, 5), 則5為主元素;又如,A=(0,5,5,3,5,1,5,7),則A中沒有主元素。假設(shè)A中的n個(gè)元素保存在一個(gè)一維數(shù)組中,請?jiān)O(shè)計(jì)一個(gè)盡可能高效的算法,找出A的主元素。若存在主元素,則輸出該元素;否則輸出-1。要求:
(1)給出算法的基本設(shè)計(jì)思想
(2)根據(jù)設(shè)計(jì)思想,采用C、C++或Java語言描述算法,關(guān)鍵之處給出注釋
(3)說明你所設(shè)計(jì)算法的時(shí)間復(fù)雜度和空間復(fù)雜度
基本設(shè)計(jì)思想:
從前往后掃描數(shù)組元素,標(biāo)記出一個(gè)可能成為主元素的元素num, 然后重新計(jì)數(shù),確認(rèn)num是否是主元素
算法實(shí)現(xiàn):
int majority(int A[], int n){int ans, cnt;ans = A[0];for(int i=1; i<n; i++){if(A[i] == ans){cnt++;}else{if(cnt > 0){cnt--;}else{ans = A[i];cnt = 1;}}}if(cnt > 0){for(i = cnt = 0; i<n; i++){if(A[i] == ans)cnt++;}}return cnt>n/2? ans: -1; }時(shí)間復(fù)雜度:O(n)
空間復(fù)雜度:O(1)
總結(jié)
- 😄
- 😢
總結(jié)
以上是生活随笔為你收集整理的天勤2022数据结构(一)线性表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Adobe Flash CS4中文版经
- 下一篇: 在word中如何设置稿纸和字帖?学会帮你