目錄:
前言:
線性表是邏輯結構,實現線性表的是存儲結構,可以是順序存儲(順序表
,例如數組)也可以是鏈式存儲(單鏈表,雙鏈表,循環鏈表,靜態鏈表
(利用數組實現,特點依然是邏輯相鄰,物理存儲不一定相鄰))
數據結構c語言定義:
//靜態分配:
#define MaxSize 50
typedef struct{
int data[MaxSize];
int length;
}seqList;
動態分配:
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef struct
{
int *data;
int length;
} seqList;
int main()
{
seqList L;
L.length=MaxSize;
//注意,malloc分配空間後,並不能初始化爲0
//calloc卻在申請後,對空間逐一進行初始化,並設置值爲0;
//L.data=(int*)calloc(L.length,sizeof(int));
L.data=(int*)malloc(sizeof(int)*L.length);
return 0;
}
練習題:
1.兩個有序數組合並
兩個 有序
順序表合併爲一個新的有序順序表,函數返回結果順序表:
c代碼:
#include <stdio.h>
#include <stdlib.h>
int * merge_array(int a[],int b[],int len_a,int len_b)
{
int len_c=len_a+len_b;
int *c=(int*)malloc(sizeof(int)*len_c);
int i=0,j=0,k=0;
while(i<len_a&&j<len_b)
{
if(a[i]<b[j]) //保存兩者中小的那一個
{
c[k]=a[i];
i++,k++;
}
else
{
c[k]=b[j];
j++,k++;
}
}
//保存剩下的一個數組裏的全部元素
while(i<len_a)
{
c[k]=a[i];
i++,k++;
}
while(j<len_b)
{
c[k]=b[j];
j++,k++;
}
return c;
}
int main()
{
int a[5]= {1,2,3,4,5};
int b[5]= {3,4,5,6,7};
int* result=merge_array(a,b,5,5);
int i=0;
for(; i<10; i++)
{
printf("%d ",result[i]);
}
return 0;
}
2.調換數組某部分得到目標順序
已知在一維數組中依次存放編寫函數交換兩者位置得到
思路: 先逆置得到:,他們各自再進行一次調換,也就是前n個逆置調換位置,後m個逆置調換位置
,就得到
輸入: 的值和數組
4 6
1 2 3 4 5 6 7 8 9 0
輸出:
7 8 9 0 1 2 3 4 5 6
5 6 7 8 9 0 1 2 3 4
c代碼:
#include <stdio.h>
#include <stdlib.h>
///輸入:待處理數組,逆置起始位置,結束位置
void exchangePlace(int A[],int start,int end)
{
int i=start,j=end;
while(i<j)
{
int tmp=A[i];
A[i]=A[j];
A[j]=tmp;
i++,j--;
}
}
//打印數組
void print(int A[],int len)
{
int i=0;
while(i<len)
{
printf("%d ",A[i]);
i++;
}
printf("\n");
}
int main()
{
int m=0,n=0;
scanf("%d %d",&m,&n);
int *A=(int*)malloc(sizeof(int)*(m+n));
int i=0;
for(i=0; i<m+n; i++)
{
scanf("%d",&A[i]);
}
exchangePlace(A,0,m+n-1);
exchangePlace(A,0,n-1);
exchangePlace(A,n,m+n-1);
print(A,m+n);
return 0;
}
3.有序單調遞增線性表的最快查找與替換
有序單調遞增線性表,設計算法用最少時間在表中查找數值爲 的元素,找到後交換它和後繼位置。
如果找不到,就插入表中,並使得表依然有序。
輸入: 數組大小M,元素x,數組的內容
4 4
1 2 3 5
輸出:
1 2 3 4 5
輸入:
4 4
1 2 4 6
輸出:
1 2 6 4
由於malloc分配空間不進行任何初始化,所以只是交換時會出現一個多餘的數,也可以自己先分配一個值來解決這個問題,或者靜態初始化數組:
#include <stdio.h>
#include <stdlib.h>
void binary_search_re(int a[],int len,int x)
{
int mid=len/2;
int start=0,end=len-1;
while(start<=end)
{
mid=(start+end)/2;
if(a[mid]>x)
{
end=mid-1;
}
else if(a[mid]<x)
{
start=mid+1;
}
else if(a[mid]==x)
{
//交換x和後面一個元素的位置,如果是最後一個,
break;
}
}
if(a[mid]==x && mid!=len-1)
{
//不是最後一個,才交換位置
int tmp=a[mid];
a[mid]=a[mid+1];
a[mid+1]=tmp;
}
if(start>end) //沒找到這個元素,
{
int i=0;
for(i=len-1; i>end; i--)
{
a[i+1]=a[i];//移動mid後面的元素
}
a[i+1]=x;//插入X
}
}
void print(int A[],int len)
{
int i=0;
while(i<len)
{
printf("%d ",A[i]);
i++;
}
printf("\n");
}
int main()
{
int len=0,x=0;
scanf("%d %d",&len,&x);
int *a=(int*)malloc(sizeof(int)*(len+1));
int i=0;
for(i=0; i<len; i++)
{
scanf("%d",&a[i]);
}
binary_search_re(a,len,x);
print(a,len+1);
return 0;
}
4.找出主元素
主元素是出現在數組中,出現次數超過了n/2次的數,
給定一個數組,問是否有主元素。
輸入:
0,5,5,3,5,7,5,5
輸出:
5
輸入
0,5,5,3,5,1,5,7
輸出:
無主元素
參考真題: 騰訊2019技術崗筆試 消消樂
只要出現次數最多的那一個數的出現次數小於等於一半就是YES,否則NO
比如:1 1 1 1 1 1 3 3 3 3 4 4
時間複雜度O(1):
掃描數組一次,遇到一個值就計數i=1;如果下一個不是這個值就i減一,如果是這個值就加一;從而有掃描完全組,倘若i>=1說明這個數是主元素。因爲如果出現次數大於一半,i的值就一定大於1,請你仔細品品。
空間複雜度也是O(1)
完全沒用到任何的棧或者鏈這類複雜數據結構。這樣做題最快而且最方便。
代碼:
#include <stdio.h>
#include <stdlib.h>
int detectMainElement(int a[],int len)
{
int count=0,i=0,main_element=a[0];
for(i=1; i<len; i++)
{
if(a[i]==main_element)
count++;
else
count--;
if(count<0)
{
main_element=a[i];
count++;
}
}
if(count>0)
return main_element;
else
return -1;
}
int main()
{
int a[8]= {0,5,5,3,5,5,5,7};
printf("%d",detectMainElement(a,8));
}
5.找出中位數
兩個有序等長序列,求他們倆的中位數,儘量時間空間上都要簡單:
例如: 的中位數就是
思路:
分別求序列的中位數 求序列A,B的中位數,
1.a=b,則a或者b就是中位數
2.a<b,捨棄A的小的一半(以a爲分割點)和B的大的一半(b爲分割)
3.a<b,捨棄A的大的一半(以a爲分割點)和B的小的一半(b爲分割),其中捨棄的部分都要一樣長。
注意處理奇數和偶數的情況!!!
由於比較簡單,就不放代碼了。
還是放一下吧,怎麼可以不寫代碼呢……
#include <stdio.h>
#include <stdlib.h>
///查找中位數
int find_mid_number(int a[],int b[],int len_a,int len_b)
{
int sa=0,sb=0,ea=len_a-1,eb=len_b-1,mid_a=0,mid_b=0;
//表示起始位置,結束位置,中間位置
while(sa<ea||sb<eb)
{
mid_a=(sa+ea)/2;
mid_b=(sb+eb)/2;
if(a[mid_a]==b[mid_b])
{
return a[mid_a];
}
if(a[mid_a]<b[mid_b])
{
if((sa+ea)%2==0) //奇數
{
sa=mid_a;
eb=mid_b;
}
else
{
sa=mid_a+1;
eb=mid_b;
}
}
else
{
if((sa+ea)%2==0) //奇數
{
sb=mid_b;
ea=mid_a;
}
else
{
sb=mid_b+1;
ea=mid_a;
}
}
}
return a[sa]<b[sb]?a[sa]:b[sb];
}
int main()
{
int a[5]={11,13,15,17,19};
int b[5]={2,4,6,8,20};
printf("%d",find_mid_number(a,b,5,5));
return 0;
}