- 線性結構
若結構是非空有限集,則有且僅有一個開始結點和一個終端結點,並且除了首尾節點外所有結點都最多隻有一個直接前趨和一個直接後繼。 可表示為:(a1,a2,a3,...)
特點:只有一個首結點和尾結點
本質特徵:除首尾結點外,其他結點只有一個直接前驅和一個直
接後繼。
簡言之,線性結構反映結點間的邏輯關係是二對一(1:1)的
線性結構包括:線性表、 堆疊、 佇列、 字串、 陣列
等,其中最典型、 最常用的是線性表
線性表
線性表邏輯結構
PS:空表分配了記憶體空間但是沒有元素,不是不存在這個表
線性表的順序表示和邏輯實現
順序表的表示
線性表的順序表的表示又叫順序儲存結構順序映像
線性表順序儲存的特點
- 邏輯上相鄰的資料元素,其物理儲存上也相鄰;
- 若已知表中首元素在儲存器中的位置則其他元素存放位置亦可求出
LOC(ai)=LOC(a0)+L*(i)
順序表的實現
(增刪改查)
- 修改
O(1)指的是對同一個元素只進行一次操作
-
增加
遍歷是從第i個到第L.length個元素
在表的第i個元素前面插入一個元素
-
刪除
刪除線性表的第個位置上的元素
-
清空和刪除表
-
排序
-
查詢
下標查詢即可
順序表的運算效率分析
同理可證: 順序表刪除一元素的時間效率(時間複雜度)為
T (n)=(n-1)/2約等於o(n)
空間複雜度:0=o(1),因為沒有使用輔助資料
深入討論
順序表各種操作的通式如何寫??
寫了一個晚上,思路不難,就是一些語法細節要注意(C語言基礎不夠牢導致的)
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int *numlist;
int length;
}chatDemo;
//氣泡排序
void bubble(int *arr,int length){
int temp=0;
for(int i=0;i<length-1;i++){
for(int j=0;j<length-i-1;j++){
if(arr[j]>arr[j+1]){
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
}
void search(chatDemo list,int tofind){//二分法查詢
int start=0;
int end=list.length-1;
int mid;
while(start<=end){
mid=(start+end)/2;
if(tofind>list.numlist[mid]){
start=mid;
}else if(tofind<list.numlist[mid]){
end=mid;
}
else if(tofind==list.numlist[mid]){
printf("the index is %d",mid);
return;
}
}
printf("404 not found");
}
void del(chatDemo *list,int position){
if(position<0||position>=list->length){
printf("OutoffpositionError");
return;
}
for(int i=position;i<list->length;i++){
list->numlist[i-1]=list->numlist[i];
}
list->numlist[list->length-1]=0;
list->length-=1;
list->numlist=(int*)realloc(list->numlist,list->length*sizeof(int));
printf("after del length:%d\n",list->length);
}
void add(chatDemo *list,int position,int addnum){
if(position<1||position>list->length){
printf("OutoffpositionError");
return;
}
list->length+=1;
list->numlist=(int*)realloc(list->numlist,list->length*(sizeof(int)));
list->numlist[list->length-1]=0;
for(int i=list->length-1;i>position-1;i--){
list->numlist[i]=list->numlist[i-1];
}
list->numlist[position-1]=addnum;
printf("after add length:%d\n",list->length);
}
int main(){
chatDemo demo;
demo.length=10;
demo.numlist=(int*)calloc(demo.length,sizeof(int));
int initial_values[] = {9, 2, 8, 3, 1, 4, 5, 6, 10, 7};
for (int i = 0; i < demo.length; i++) {
demo.numlist[i] = initial_values[i];
}
bubble(demo.numlist,demo.length);
printf("排序後陣列\n");
for (int i = 0; i < demo.length; i++) {
printf("%d\n",demo.numlist[i]);
}
del(&demo,4);
printf("陣列長度是%d\n",demo.length);
for(int i=0;i<demo.length;i++){
printf("%d\n",demo.numlist[i]);
}
add(&demo,4,4);
printf("陣列長度是%d\n",demo.length);
for(int i=0;i<demo.length;i++){
printf("%d\n",demo.numlist[i]);
}
search(demo,8);
free(demo.numlist);
return 0;
}
抽象資料型別
線性表的鏈式表示和邏輯實現
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
typedef struct Node
{
int data; //資料域
struct Node *next; //指標域,構建遞迴結構
}Node;
typedef struct {
Node *head; // 頭指標
Node *tail;
size_t length;
// 尾指標
} List;
void InitList(List *list);//初始化
void push_tail(List *list,int x);//尾插
void push_head(List *list,int x);//頭插
void show_list(List *list);//列印連結串列
void delAimval(List *list,int x,int ifone);//刪除指定元素
void add(List *list,int x,int position,int fa);//指定位置前或後插入
void reverse(List*list);//逆序
Node *find(List *list,int x);//查詢元素第一次出現位置,修改//
int main(){
int numlist[]={0,1,2,5,5,6,7,8,9,8,5,2,1,1};
int len=(int)(sizeof(numlist)/sizeof(int));
int i=0;
List demo,demox;
InitList(&demo);
InitList(&demox);
while(i<len){
push_tail(&demo,numlist[i++]);
}
printf("尾插法建立\n");
show_list(&demo);
i--;
while(i>=0){
push_head(&demox,numlist[i--]);
}
printf("頭插法建立\n");
show_list(&demox);
reverse(&demox);
printf("逆序後\n");
show_list(&demox);
delAimval(&demox,5,1);
printf("刪除一次指定元素5後\n");
show_list(&demox);
delAimval(&demox,5,0);
printf("刪除全部指定元素5後\n");
show_list(&demox);
printf("後插元素\n");
add(&demox,99,6,1);
show_list(&demox);
printf("前插元素\n");
add(&demox,99,6,0);
show_list(&demox);
find(&demox,2);
return 0;
}
//初始化
void InitList(List *list)
{
Node* headNode=(Node*)malloc(sizeof(Node));//此時頭指標指向頭節點
list->head=headNode;
assert(list->head!=NULL);
list->head->next=NULL;
list->tail = list->head; //尾指標也一起指向頭節點。
list->length=0;
}
void push_head(List *list,int x){
Node *new_node=(Node*)malloc(sizeof(Node));
assert(new_node!=NULL);
new_node->data=x;
new_node->next=NULL;
//第一個節點的插入需要改尾指標的指向
if(list->length==0){
list->tail=new_node;
}
new_node->next=list->head->next;
list->head->next=new_node;
list->length++;
}
void push_tail(List *list,int x){
Node *new_node=(Node*)malloc(sizeof(Node));
assert(new_node!=NULL);
new_node->data=x;
new_node->next=NULL;
// 將當前尾節點的next指向新節點
list->tail->next = new_node;
// 更新尾指標
list->tail = new_node;
list->length++;
}
void show_list(List *list)
{
Node *p = list->head->next;
while(p!=NULL){
printf("%d-->",p->data);
p=p->next;
}
printf("NULL\n");
}
Node *find(List *list,int x){
int j=1;
Node *p=list->head->next;
while(p){
if(p->data==x){
//可以同時修改元素,這裡就不實現了
break;
}else{
j++;
p=p->next;
}
}
printf("%d是第%d個元素",x,j);
return p;
}
void delAimval(List*list,int x,int ifone){
Node *p=list->head;
while(p!=NULL&&p->next!=NULL){
if(p->next->data==x){
Node *p2=p->next->next;
Node *p1=p->next;
p->next=p2;
free(p1);
list->length--;
if(ifone==1){break;}else if(ifone==0){
p=list->head;
continue;
}else{printf("ffsr");}
}else{
p=p->next;
}
}
}
void add(List *list,int x,int position,int fa){
int j=1;
Node *new_node=(Node*)malloc(sizeof(Node));
new_node->data=x;
if(position<1||position>(int)list->length){
printf("DIANLAO");
return;
}
if(fa==0){
//前插
Node *p=list->head;
while(p&&p->next){
if(j==position){
new_node->next=p->next;
p->next=new_node;
list->length++;
break;
}else{p=p->next;j++;}
}
}else if(fa==1){
//後插
Node *p=list->head->next;
while(p){
if(j==position){
new_node->next=p->next;
p->next=new_node;
list->length++;
break;
}else{
p=p->next;
j++;
}
}
}
}
void reverse(List*list){
Node* previous=NULL;
Node* current=list->head->next;
Node*next=NULL;
while(current!=NULL){
next=current->next;// 儲存下一個節點
current->next=previous;// 當前節點指向前一個節點
previous=current;// 前一個節點移動到當前節點
current=next;// 當前節點移動到下一個節點
}
list->head->next=previous;
}
執行結果