1.數據元素之間不是獨立的,存在特定的關係,這些關係即結構。所以數據結構是指數據對象中數據元素之間的關係。
數據結構分爲邏輯結構和物理結構。
邏輯結構分爲:
集合結構:數據元素之間沒有特別的關係,僅同屬相同集合。
線性結構:數據元素之間是一對一的關係。
樹形結構:數據元素之間存在一對多的層次關係。
圖形結構:數據元素之間是多對多的關係。
物理結構分爲:
順序存儲結構:將數據存儲在地址連續的存儲單元裏。
鏈式存儲結構:將數據存儲在任意的存儲單元裏,通過保存地址的方式找到相關聯的數據元素。
線性表的定義:
線性表(List)是零個或多個數據元素的集合。
線性表中的數據元素之間是有順序的。
線性表中的數據元素個數是有限的。
線性表中的數據元素的類型必須相同。
性質:
a0爲線性表的第一個元素只有一個後繼。
an爲線性表的最後一個元素,只有一個前驅。
除a0和an外的其他元素既有前驅又有後繼。
線性表能夠逐項訪問和順序存取。
2.順序存儲結構:線性表的順序存儲結構指的是用一段地址連續的存儲單元依次存儲線性表的數據元素。
(1)插入元素算法:
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if (L->length==MAXSIZE) /* 順序線性表已經滿 */
return ERROR;
if (i<1 || i>L->length+1) /* 當i比第一位置小或者比最後一位置後一位置還要大時 */
return ERROR;
if (i<=L->length) /* 若插入數據位置不在表尾 */
{
for(k=L->length-1;k>=i-1;k--) /* 將要插入位置之後的數據元素向後移動一位 */
L->data[k+1]=L->data[k];
}
L->data[i-1]=e; /* 將新元素插入 */
L->length++;
return OK;
}
(2)刪除元素算法:
Status ListDelete(SqList *L,int i,ElemType *e)
{
int k;
if (L->length==0) /* 線性表爲空 */
return ERROR;
if (i<1 || i>L->length) /* 刪除位置不正確 */
return ERROR;
*e=L->data[i-1];
if (i<L->length) /* 如果刪除不是最後位置 */
{
for(k=i;k<L->length;k++) /* 將刪除位置後繼元素前移 */
L->data[k-1]=L->data[k];
}
L->length--;
return OK;
}
3.鏈式存儲結構:
爲了表示每個元素與其直接後繼元素之間的邏輯關係,每個元素除了存儲本身的信息外,還需要存儲指示其直接後繼的信息。
鏈表的概念:
表頭結點------鏈表中的第一個結點,包含指向第一個數據元素的指針以及鏈表自身的一些信息。
數據結點------鏈表中代表數據元素的結點,包含指向下一個數據元素的指針和數據元素的信息。
尾結點--------鏈表中的最後一個數據結點,其下一元素指針爲空,表示無後繼。
N個結點鏈接成一個鏈表,即爲線性表(a1,a2,…an)的鏈式存儲結構,因爲此鏈表的每個結點中只包含一個指針域,所以叫單鏈表。
鏈表中第一個結點的存儲位置叫做頭指針;最後一個結點指針爲空(NULL)。
可在單鏈表的第一個結點前附設一個結點,稱爲頭結點。可以不存儲任何信息。
(1)單鏈表整表創建的算法思路:
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0)); /* 初始化隨機數種子 */
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL; /* 先建立一個帶頭結點的單鏈表 */
for (i=0; i<n; i++)
{
p = (LinkList)malloc(sizeof(Node)); /* 生成新結點 */
p->data = rand()%100+1; /* 隨機生成100以內的數字 */
p->next = (*L)->next;
(*L)->next = p;
/* 插入到表頭 */
}
}
上面那種叫做頭插法,我們也可以通過尾插法來創建一個鏈表
void CreateListTail(LinkList *L, int n)
{
LinkList p,r;
int i;
srand(time(0)); /* 初始化隨機數種子 */
*L = (LinkList)malloc(sizeof(Node)); /* L爲整個線性表 */
r=*L; /* r爲指向尾部的結點 */
for (i=0; i<n; i++)
{
p = (Node *)malloc(sizeof(Node)); /* 生成新結點 */
p->data = rand()%100+1; /* 隨機生成100以內的數字 */
r->next=p; /* 將表尾終端結點的指針指向新結點 */
r = p; /* 將當前的新結點定義爲表尾終端結點 */
}
r->next = NULL; /* 表示當前鏈表結束 */
}
(2)獲取鏈表第i個數據的算法思路:
Status GetElem(LinkList L,int i,ElemType *e)
{
int j;
LinkList p; /* 聲明一結點p */
p = L->next; /* 讓p指向鏈表L的第一個結點 */
j = 1;
/* j爲計數器 */
while (p && j<i) /* p不爲空或者計數器j還沒有等於i時,循環繼續 */
{
p = p->next; /* 讓p指向下一個結點 */
++j;
}
if ( !p || j>i )
return ERROR; /* 第i個元素不存在 */
*e = p->data; /* 取第i個元素的數據 */
return OK;
}
(3)單鏈表第i個數據插入結點的算法思路:
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L;
j = 1;
while (p && j < i) /* 尋找第i個結點 */
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR; /* 第i個元素不存在 */
s = (LinkList)malloc(sizeof(Node)); /* 生成新結點(C語言標準函數) */
s->data = e;
s->next = p->next; /* 將p的後繼結點賦值給s的後繼 */
p->next = s; /* 將s賦值給p的後繼 */
return OK;
}
(4)單鏈表第i個數據刪除結點的算法思路:
Status ListDelete(LinkList *L,int i,ElemType *e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while (p->next && j < i)
/* 遍歷尋找第i個元素 */
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return ERROR; /* 第i個元素不存在 */
q = p->next;
p->next = q->next;
/* 將q的後繼賦值給p的後繼 */
*e = q->data; /* 將q結點中的數據給e */
free(q); /* 讓系統回收此結點,釋放內存 */
return OK;
}
順序表與單鏈表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.