目錄node
一元多項式:\(f(x)=a_0+a_1x+\cdots+a_{n-1}x^{n-1}+a_nx^n\)python
主要運算:多項式相加、相減、相乘等數組
如何用程序設計語言表示多項式,而且實現對多項式的操做?數據結構
數組各份量對應多項式各項:a[i]
表示項\(x^i\)的係數\(a_i\)app
例如:\(f(x)=4x^5-3x^2+1\)post
表示以下圖所示:性能
兩個多現實相加:兩個數組對應份量相加spa
問題:如何表示多項式\(x+3x^{2000}\),至少要有2001個份量表示,而且20001個份量中只有兩項是非零的,這樣的表示方法是有很大問題的設計
每一個非零項\(x_ix^i\)涉及兩個信息:係數\(a_i\)和指數\(i\)3d
能夠將一個多項式當作是一個\((a_i,i)\)二元組的集合。
用結構數組表示:數組份量是由係數\(a_i\)、指數\(i\)組成的結構,對應一個非零項
例如:\(P_1(x)=9x^{12}+15x^8+3x^2\)和\(P_2(x)=26x^{19}-4x^8-13x^6+82\)
按指數大小有序存儲!
相加過程:從頭開始,比較兩個多項式當前對應項的指數
$ P1: (9,12), (15,8), (3,2) $
$ P2: (26,19), (-4,8), (-13,6), (82,0) $
$P3: (26,19) (9,12) (11,8) (-13,6) (3,2) (82,0) $
\(P_3(x)=26x^{19}+9x^{12}+11x^8-13x^6+3x^2+82\)
鏈表中每一個結點存儲多項式中的一個非零項,包括係數和指數兩個數據域寄一個指針域
/* c語言實現 */ typedef struct PolyNode *Polynomial; struct PolyNode{ int coef; int expon; Polynomial link; }
# python語言實現 class PolyNode(): def __init__(coef, expon): self.coef = coef self.expon = expon self.next = None
例如:
\[ \begin{aligned} & P_1(x) = 9x^{12}+15x^8+3x^2 \\ & P_2(x) = 26x^{19}-4x^8-13x^6+82 \end{aligned} \]
鏈表存儲形式爲:
鏈表形式表現的多項式加法過程相似於前兩種方法。
多項式表示問題的啓示:
「線性表(Linear List)」:由同類型數據元素構成有序序列的線性結構
類型名稱:線性表(List)
數據對象集:線性表是\(n(\geq{0})\)個元素構成的有序序列\((a_1,a_2,\dots,a_n)\)
操做集:線性表\(L\in{List}\),整數\(i\)表示位置,元素\(X\in{ElementType\),線性表基本操做主要有:
List MakeEmpty():
初始化一個空線性表\(L\);ElementType FindKth( int K, List L ):
根據位序\(K\),返回相應元素 ;int Find( ElementType X, List L ):
在線性表\(L\)中查找\(X\)的第一次出現位置;void Insert( ElementType X, int i, List L):
在位序\(i\)前插入一個新元素\(X\);void Delete( int i, List L ):
刪除指定位序\(i\)的元素;int Length( List L ):
返回線性表\(L\)的長度\(n\)。利用數組的連續存儲空間順序存放線性表的各元素
/* c語言實現 */ typedef struct LNode *List; /* 定義結構體指針 */ struct LNode{ ElementType Data[MAXSIZE]; /* 數組類型的Data,數組最大長度爲MAXSIZE */ int Last; }; /* 定義結構體 */ struct LNode L; /* 聲明變量L */ List PtrL; /* 聲明結構體PtrL */
訪問下標爲\(i\)的元素:L.Data[i]
或PtrL->Data[i](取出PtrL所指向的結構體中包含的數據項Data[i])
線性表的長度:L.Last+1
或PtrL->Last+1(取出PtrL所指向的結構體中包含的數據項Last並加1)
/* c語言實現 */ List MakeEmpty() { List PtrL; PtrL = (List)malloc(sizeof(struct LNode)); /* 申請一個結構體 */ PtrL->Last = -1; return PtrL; }
查找成功的平均比較次數爲\((n+1)/2\),平均時間性能爲\(O(n)\)
/* c語言實現 */ int Find(ElementType X, List Ptrl) { int i = 0; while (i <= Ptrl->Last && Ptrl->Data[i] != X) i++; if (i > Ptrl->Last) return -1; /* 若是沒找到,返回-1 */ else return i; /* 找到後返回的事存儲位置 */
平均移動次數爲\(n/2\),平均時間性能爲\(O(n)\)
/* c語言實現 */ void Insert(ElementType X, int i, List PtrL) { int j; if (Ptrl->Last == MAXSIZE - 1){ /* 表空間已滿,不能插入 */ printf("表滿"); return ; } if (i<1 || PtrL->Last+2){ printf("位置不合法"); return ; } for (j=PtrL->Last; j>=i-1; j--) PtrL->Data[j+1] = Ptrl->Data[j]; /*將a_i~a_n倒序向後移動*/ PtrL->Data[i-1] = X; /* 新元素插入 */ PtrL->Last++; /* Last仍指向最後元素 */ return; }
平均移動次數爲\((n-1)/2\),平均時間性能爲\(O(n)\)
/* c語言實現 */ void Delete(int i, List Ptrl) { int j; if(i<1 || i>PtrL->Last+1){ /* 檢查空表及刪除位置的合法性 */ printf("不存在第%d個元素", i); return ; } for (j=i, j<=Ptrl->Last; j++) PtrL->Data[j-1] = Ptrl->Data[j]; /* 將a_{i+1}~a_n順序向前移動*/ Ptrl->Last--; /* Last仍指向最後元素 */ return; }
不要求邏輯上相鄰的兩個元素物理上也相鄰;經過「鏈」創建起數據元素之間的邏輯關係。即插入、刪除不須要移動數據元素,只須要修改「鏈」。
/* c語言實現 */ typedef struct LNode *List; struct LNode{ ElementType Data; List Next; }; struct Londe L; List PtrL;
時間性能爲\(O(n)\)
/* c語言實現 */ int Length(List PtrL) { List p = PtrL; /* p指向表的第一個結點 */ int j = 0; while (p) { p = p->Next; j++; /* 當前p指向的是第j個結點 */ } return j; }
平均時間性能爲\(O(n)\)
/* c語言實現 */ List FindKth(int K, List PtrL) { List p = Ptrl; int i = 1; while (p != NULL && i < K){ p = p->Next; i++; } if (i==K) return P; /* 找到第K個,返回指針 */ else return NULL; /* 不然返回空 */
/* c語言實現 */ List Find(ElementType X, List PtrL) { List p = PtrL; while (p != NULL && p->Data != X) p = p->Next; return p; }
插入(在第\(i-1(1\leq{i}\leq{n+1})\)個結點後插入一個值爲\(X\)的新結點)
先構造一個新結點,用s指向;
而後修改指針,插入結點(\(p\)以後插入新結點是\(s\))
/* c語言實現 */ List Insert(ElementType X, int i, List PtrL) { List p, s; if (i == 1){ /* 新結點插入在表頭 */ s = (List)malloc(sizeof(struct LNode)); /* 申請、填裝結點 */ s->Data = X; s->Next = Ptrl; return s; /* 返回新表頭指針 */ } p = FindKth(i-1, Ptrl); /* 查找第i-1個結點 */ if (p == NULL){ /* 第i-1個不存在,不能插入 */ printf("參數i錯"); return NULL; }else{ s = (List)malloc(sizeof(struct LNode)); /* 申請、填裝結點 */ s->Data = X; s->Next = p->Next; /* 新結點插入在第i-1個結點的後面*/ p->Next = s; return PtrL; }
平均查找次數爲\(n/2\),平均時間性能爲\(O(n)\)
/* c語言實現 */ List Delete(int i, List PtrL) { List p, s; /* 若要刪除的事表的第一個結點 */ if (i == 1){ s = PtrL; /* s指向第1個結點 */ if (PtrL != NULL) PtrL = PtrL->Next; /* 從鏈表中刪除 */ else return NULL; free(s); /* 釋放被刪除結點 */ return PtrL; } p = FindKth(i-1, PtrL); /* 查找第i-1個結點 */ if (p == NULL){ printf("第%d個結點不存在", i-1); return NULL; } else if (i->Next == NUll){ printf("第%d個結點不存在", i); return NULL; } else { s = p->Next; /* s指向第i個結點 */ p->Next = s->Next; /* 從鏈表中刪除*/ free(s); /* 釋放被刪除結點*/ return PtrL; }
咱們知道了一元多項式的表示,那麼二元多項式又該如何表示?好比,給定二元多項式:\(P(x,y)=9x^{12}y^2+4x^{12}+15x^8y^3-x^8y+3x^2\)
能夠將上述二元多項式當作關於\(x\)的一元多項式:\(P(x,y)=(9y^2+4)x^{12}+(15y^3-y)x^8+3x^2\quad(ax^{12}+bx^8+cx^2)\)
所以,上述二元多項式能夠用「複雜」鏈表表示爲下圖所示:
/* c語言實現 */ typedef struct GNode *GList; struct GNode{ int Tag; /* 標誌域:0表示結點是單元素,1表示結點是廣義表 */ union{ /* 字表指針域Sublist與單元素數據域Data複用,即公用存儲空間 */ ElementType Data; Glist SubList; }URegion; Glist Next; /* 指向後繼結點 */ }
多重鏈表:鏈表中的結點可能同時隸屬於多個鏈
多重鏈表有普遍的用途:基本上如樹、圖這樣相對複雜的數據結構都能夠採用多重鏈表方式實現存儲。
矩陣能夠用二維數組表示,但二維數組表示有兩個缺陷:
\[ A=\begin{bmatrix} 18&0&0&0&2&0 \\ 0&27&0&0&0&0 \\ 0&0&0&0&-4&0 \\ 23&-1&0&0&0&12 \end{bmatrix} \]
\[ B=\begin{bmatrix} 0&2&11&0&0&0& \\ 3&-4&-1&0&0&0 \\ 0&0&0&9&13&0 \\ 0&-2&0&0&10&7 \\ 6&0&0&5&0&0 \\ \end{bmatrix} \]
分析:採用一種典型的多重鏈表——十字鏈表來存儲稀疏矩陣
只存儲矩陣非0元素相:結點的數據域:行座標\(Row\)、列座標\(Col\)、數值\(Value\)
每一個結點經過兩個指針域,把同行、同列串起來;
行指針(或稱爲向右指針)Right
列指針(或稱爲向下指針)Down
下圖爲矩陣A的多重鏈表圖:
用一個標識域\(Tag\)來區分頭結點和非0元素結點;
頭結點的標識值爲「Head」,矩陣非0元素結點的標識值爲「Term」。
class Node(object): def __init__(self, val, p=0): self.data = val self.next = p class LinkList(object): def __init__(self): self.head = 0 def __getitem__(self, key): if self.is_empty(): print('linklist is empty.') return elif key < 0 or key > self.getlength(): print('the given key is error') return else: return self.getitem(key) def __setitem__(self, key, value): if self.is_empty(): print('linklist is empty.') return elif key < 0 or key > self.getlength(): print('the given key is error') return else: self.delete(key) return self.insert(key) def initlist(self, data): self.head = Node(data[0]) p = self.head for i in data[1:]: node = Node(i) p.next = node p = p.next def getlength(self): p = self.head length = 0 while p != 0: length += 1 p = p.next return length def is_empty(self): if self.getlength() == 0: return True else: return False def clear(self): self.head = 0 def append(self, item): q = Node(item) if self.head == 0: self.head = q else: p = self.head while p.next != 0: p = p.next p.next = q def getitem(self, index): if self.is_empty(): print('Linklist is empty.') return j = 0 p = self.head while p.next != 0 and j < index: p = p.next j += 1 if j == index: return p.data else: print('target is not exist!') def insert(self, index, item): if self.is_empty() or index < 0 or index > self.getlength(): print('Linklist is empty.') return if index == 0: q = Node(item, self.head) self.head = q p = self.head post = self.head j = 0 while p.next != 0 and j < index: post = p p = p.next j += 1 if index == j: q = Node(item, p) post.next = q q.next = p def delete(self, index): if self.is_empty() or index < 0 or index > self.getlength(): print('Linklist is empty.') return if index == 0: q = Node('', self.head) self.head = q p = self.head post = self.head j = 0 while p.next != 0 and j < index: post = p p = p.next j += 1 if index == j: post.next = p.next def index(self, value): if self.is_empty(): print('Linklist is empty.') return p = self.head i = 0 while p.next != 0 and not p.data == value: p = p.next i += 1 if p.data == value: return i else: return -1 l = LinkList() l.initlist([1, 2, 3, 4, 5]) print(l.getitem(4)) # 5 l.append(6) print(l.getitem(5)) # 6 l.insert(4, 40) print(l.getitem(3)) # 4 print(l.getitem(4)) # 40 print(l.getitem(5)) # 5 l.delete(5) print(l.getitem(5)) # 6 l.index(5)