小程式獲取html格式解析亂碼
阿新 • • 發佈:2021-01-17
技術標籤:Data Structure資料結構
線性表
- 線性表有兩種儲存結構:順序表,連結串列
- 儲存密度=
結
點
中
數
據
元
素
所
佔
的
存
儲
量
結
點
所
佔
的
存
儲
量
\frac{結點中資料元素所佔的儲存量}{結點所佔的儲存量}
結點所佔的存儲量結點中數據元素所佔的存儲量
順序表的儲存密度=1;連結串列的儲存密度<1。
線性表的順式儲存結構:順序表
順序表的所有資料元素在儲存器中佔有一整塊儲存空間,且兩個邏輯上相鄰的元素在儲存器中的儲存位置也相鄰。
順序表的結構
typedef struct { elemtype data[MaxSize]; //存放線性表中的元素 int lenth; //存放線性表的長度 }SQlist;
順序表的建立
void CreateList(SQlist *&L, elemtype a[], int n) { int i = 0; int k = 0; //k為線性表L中的元素個數,也是線性表的長度 L = (SQlist *)malloc(sizeof(SQlist)); while(i<n) //將a中的元素逐個掃描入L { L->data[k] = a[i]; k++; i++; } L->length = k; //L的長度為k }
初始化順序表
void InitList(SQlist *&L) //在實際運用中,初始化最好在主函式中進行
{
L = (SQlist *)malloc(sizeof(SQlist));
L->length = 0; //線性表的長度初始化為0
}
順序表的銷燬
void DestroyList(SQlist *&L)
{
free(L);
}
判斷順序表是否為空表
bool ListEmpty(SQlist *L)
{
return (L->length==0);
}
求順序表的長度
int Length(SQlist L) //一個沒有什麼存在意義的函式 { return(L->length); }
順序表的輸出
void OutputList(SQlist *L)
{
for(int i=0;i<L->length;i++)
{
printf("%d",L->length);
}
}
查詢順序表中的某個元素值的下標
int LocateElem(SQlist *L, ElemType e)//查詢順序表中值為e的元素,如果查詢成功,返回元素位序,否則返回0
{
int i;
for(i=0;i<L->length;i++)
{
if(L->data[i]==e)
{
return i+1; // 下標為i的元素值等於e,返回其位號i+1
}
}
return 0; //退出迴圈,說明查詢失敗
}
插入元素
void Insert(SQlist *&L,int i,elemtype e) //在順序表L的第i個位置上插入e
{
int j = 0;
if(i<1 || i>L->length+1 || L->length==MaxSize) //插入不成功的情況
{
return ;
}
i--; //將邏輯序號轉為物理序號
for(j=L->length; j>i; j--) //將data[i]及後面的元素後移一個位置
{
L->data[j]=L->data[j-1];
}
L->data[i] = e; //插入元素e
L->length++; //順序表長度增1
}
該演算法的平均時間複雜度為O(n)。
刪除元素
int Delete(SQlist *&L,int i) //刪除順序表L的第i個元素,並返回被刪除的元素的值
{
int e; //存放被刪除的元素
int j;
if(i<1 || i>L->length)
{
return;
}
i--; //將邏輯序號轉為物理序號
e = L->data[i];
for(j=i; j<L->length-1; j++) //將data[i]之後的元素全部前移一個位置
{
L->data[j] = L->data[j+1];
}
L->length--; //順序表長度減一
}
該演算法的平均時間複雜度為O(n)。
int Delete(SQlist*&L,int x) //刪除順序表中所有值等於x的元素
{
int k; //k記錄不等於x的元素的個數
for(int i=0; i<L->length; i++)
{
if(L->data[i]!=x)
{
L->data[k] = L->data[i];
k++;
}
}
L->length = k;
}
該演算法的平均時間複雜度為O(n)。
線性表的鏈式儲存結構:連結串列
- 不同於順序表,使用連結串列儲存的資料元素,其物理儲存位置是隨機的。
- 連結串列中每個資料的儲存都由以下兩部分組成:
- 資料元素本身,其所在的區域稱為資料域;
- 指向直接後繼元素的指標,其所在的區域稱為指標域
單鏈表
單鏈表的結構
typedef struct LNode
{
int data;
struct LNode *next;
}LinkNode;
單鏈表的建立
1.頭插法
void CreateList(LinkNode *&L,int a[],int n) //n為結點總個數
{
LinkNode * s;
L=(LinkNode *)malloc(sizeof(LinkNode)); //建立頭結點
L->next=NULL;
for(int i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode)); //迴圈建立結點
s->data = a[i]; //結點賦值
s->next = L->next; //設定結點位置:結點位於頭結點之後,原首結點之前
L->next = s;
}
}
2.尾插法
void CreateList(LinkNode *&L,int a[],int n)
{
LinkNode *s, *r; //r為指向尾結點的指標
L=(LinkNode *)malloc(sizeof(LinkNode)); //建立頭結點
r=L; //將r初始化為頭結點
for(int i = 0; i<n; i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode)); //迴圈建立結點
s->data = a[i]; //結點賦值
r->next = s; //設定結點位置:原尾結點r之後
r = s; //新的尾結點為r
}
r->next=NULL;
}
單鏈表的銷燬
void DestoryList(LinkNode *& L)
{
LinkNode *pre = L; //pre為要刪除的結點,初始化為頭結點
LinkNode *p = L->next; //p始終為pre的後繼節點
while(p!=NULL)
{
free(pre); //刪除結點
pre = p; //後移pre
p = p->next; //後移p
}
free(pre); //迴圈結束時,pre為尾結點,刪除尾結點
}
判斷單鏈表是否為空表
bool ListEmpty(LinkNode *L)
{
return(L->next==NULL);
}
求單鏈表的長度
int Length(LinkNode *L)
{
int count = 0; //count為計數器
LinkNode *p = L; //從頭結點開始
while(p)
{
count++;
p = p->next; //後移p
}
return count;
}
按下標查詢元素值
根據下標i,查詢對應的元素值並返回。
int GetElement(LinkNode *L,int i)
{
int e = 0; //用於儲存下標i對應的元素值
LinkNode *p = L;
if(i<=0)
return 0; //輸入的下標不大於0,則返回0報錯
while( p!=NULL && j<i )
{
p=p->next;
j++;
}
if(p == NULL) //如果單鏈表中不存在下標為i的結點或者對應的結點為空
return 0;
else
{
e = p->data;
return e;
}
}
按已知值查詢對應下標
根據已給出的值e,查詢其對應的下標並返回。
int GetElement(LinkNode *L,int e)
{
int i = 1;
LinkNode *p = L->next; //頭結點下標記為 0,首結點的下標記為 1
while( p!=NULL && p->data!=e )
{
p=p->next;
i++;
}
if(p==NULL)
return 0; //如果單鏈表中不存在該值e
else
return i;
}
向單鏈表插入元素
將資料元素e插入到下標為i的結點中。
void ListInsert(LinkNode *&L; int i;int e)
{
int j=0;
LinkNode *p = L;
LinkNode *s;
if( i<=0 )
return ;
while( j<i-1 && p!=NULL ) //不斷迴圈直到找到下標為i-1的結點
{
p = p->next;
j++;
}
if( p==NULL )
{
return ; //如果不存在下標為i-1的結點,直接停止呼叫
}
else
{
s=(LinkNode*)malloc(sizeof(LinkNode)); //建立新的結點
s->data = e; //新結點的賦值
s->next = p->next; //新結點s位於p的下一個結點之前
p->next = s; //新結點s位於p之後
return ;
}
}
刪除資料元素
刪除下標為i的結點。
void ListDelete(LinkNode *&L; int i)
{
int j=0;
LinkNode *p = L;
LinkNode *s;
if( i<=0 )
return ;
while( j<i-1 && p!=NULL ) //不斷迴圈直到找到下標為i-1的結點
{
p = p->next;
j++;
}
if( p==NULL )
{
return ; //如果不存在下標為i-1的結點,直接停止呼叫
}
else
{
s = p->next; //p的下一個結點即為要刪除的結點
p->next = p->next->next; //將p的next指標指向被刪除結點的下一個結點
free(s);
return ;
}
}
雙鏈表
雙鏈表的結構
typedef struct DNode
{
int data;
struct DNode *prior; //指向前驅結點
struct DNode *next; //指向後繼結點
}DLinkNode;
雙鏈表的建立
1.頭插法
void CreateList(DLinkNode *&L,int a[],int n)
{
DLinkNode *s;
L = (DLinkNode*)malloc(sizeof(DLinkNode)); //建立頭結點
L->prior = L->next = NULL;
for(int i=0; i<n; i++)
{
s = (DLinkNode*)malloc(sizeof(DLinkNode)); //迴圈建立新結點
s->data = a[i]; //新結點賦值
s->next = L->next; //每個新結點都位於頭結點之後
if(L->next!=NULL)
{
L->next = L->prior = s; // 若頭結點的後繼結點不為空,則頭結點的後繼結點的前驅結點為新結點
}
L->next = s; //頭結點的新後繼節點為剛建立的s結點
s->prior = L; //剛建立的s結點的前驅結點為頭結點
}
}
2.尾插法
void CreateList(DLinkNode *&L,int a[],int n)
{
DLinkNode *s,*r; //尾插法必備兩個指標
L = (DLinkNode*)malloc(sizeof(DLinkNode)); //建立頭結點
L->prior = L->next = NULL;
r = L; //r始終指向尾結點,初始化為頭結點
for(int i=0; i<n; i++)
{
s = (DLinkNode*)malloc(sizeof(DLinkNode)); //迴圈建立新結點
s->data = a[i]; //新結點賦值
r->next = s; //尾結點的後繼結點為新結點s
s->prior = r; //新結點s的前驅結點為原尾結點r
r = s; //s成為新的尾結點
}
}
迴圈連結串列
迴圈單鏈表的建立
LinkNode *(LinkNode *&L,int a[],int n)
{
LinkNode *p;
LinkNode *s;
L = (LinkNode*)malloc(sizeof(LinkNode));
L->next = NULL;
s=L;
for(int i=0; i<n; i++)
{
p=(LinkNode*)malloc(sizeof(LinkNode));
p->data = a[i];
s->next = p;
s = p;
}
s->next = L;
return L;
}