数据结构之线性结构之线性表
一. 线性表及其实现
如何表示多项式:f(x)=a0+a1x+...+an-1xn-1+anxn
- 多项式的项数n;
- 各项系数 ai 及指数 i
顺序存储结构直接表述:一般数组
顺序存储结构表示非零项:结构数组
方法二中如果要对各项进行相加时,注意两项的指数需要按照降序或者升序排列
链表结构存储非零项
线性表:由同类型数据元素(可以是自定义的结构体等)构成有序序列的线性结构
线性表的顺序存储实现:利用数组的连续存储空间顺序存放线性表的各元素
#define MAXSIZE 10 typedef struct { int Data[MAXSIZE]; int Last; }List; List L, *PtrL; //访问下标为i的元素:L.Data[i]或者PtrL->Data[i] //线性表的长度:L.Last+1或者PtrL->Last+1;由于数组从0开始,而Last表示数组的下标
主要操作的实现
初始化
List *MakeEmpty() { List *PtrL = new List;//new的操作:申请存储空间并且初始化 PtrL->Last = -1; return PtrL; }
查找
int Find(int X, List *PtrL) { int i = 0; while (i<=PtrL->Last&&PtrL->Data[i]!=X)//i<ptrl的长度,并没找到x时继续往下找 { i++; } if (i>PtrL->Last) { return -1; } else { return i; } }
插入:先移动再插入
由于数组从0开始,第 i 个位置对应的下标数为 i-1
void Insert(int X, int i, List *PtrL)//X为插入的数字,i为插入的位置 { if (PtrL->Last == MAXSIZE - 1)//先检查表是否还有空间,如果表空间已满,不能再插入 { printf("表满"); return; } if(i<1||i>PtrL->Last+1) { printf("插入位置不合法"); return; } for (int j = PtrL->Last; j >=i-1; j--) { PtrL->Data[j + 1] = PtrL->Data[j];//从数组最后一个数开始往后移一,直到移动到i-1位置位置,此时i-1的位置为空 } PtrL->Data[i - 1] = X;// 插入新元素 PtrL->Last++; //last指向的位置也要往后移动1 return; }
删除:后面元素依次往前移动
void Delete( int i, List *PtrL)//i为删除的位置 { if (i<1 || i>PtrL->Last + 1) { printf("插入位置不合法"); return; } for (int j = i; j <=PtrL->Last; j++) { PtrL->Data[j - 1] = PtrL->Data[j];//从第i位置开始,后面依次往前移动一个位置 } PtrL->Last--; //last指向的位置也要往后移动1 return; }
线性表的链式存储实现:逻辑上相邻,物理存储位置上不相邻
插入删除不需要移动数据元素,只需要修改链
typedef struct Node { int Data; struct Node *Next; } ListNode; ListNode LN, *PtrlN;
主要操作
求表长
int Length(ListNode *PtrlN) { ListNode *p = PtrlN;//定义一个临时变量指向表的第一个结点 int j = 0; while (p) { p = p->Next; j++; //当前p指向第j个结点 } return j; }
查找
按序号查找:FindKth;
ListNode *FindKth(int K, ListNode *PtrlN)//K为需要找到的序号为K的,即第K个 { ListNode *p = PtrlN; int i = 1; while (p!=NULL&&i<K) { p = p->Next; i++; } if (i == K) return p; else return NULL; }
按元素查找:FindKth;
ListNode *Find(int X, ListNode *PtrlN)//X为需要查找的元素 { ListNode *p = PtrlN; while (p!=NULL&&p->Data!=X) { p = p->Next; } return p; } //返回值为null,则说明没有找到
插入
先找到插入点之前的那个结点,即i-1的结点
ListNode *Insert(int X, int i, ListNode *PtrlN)//X为插入的数字,i为插入的位置 { ListNode *p; if (i==1)//新结点插入在表头 { ListNode *s = new ListNode; s->Data = X; s->Next = PtrlN; return s; } p = FindKth(i - 1, PtrlN); if (p==NULL) { printf("参数i出错"); return NULL; } else { ListNode *s = new ListNode; s->Data = X; s->Next = p->Next; p->Next = s; //注意,此处和上面一个语序不能颠倒,否则s的next还是s return PtrlN; } }
一段存储空间存放链表,ptrlN和p都只是指向其中的一个指针,指向哪个位置,就从该位置开始一直到链表的最后
删除
删除一定要记住释放删除点的内存
ListNode *Delete(int i, ListNode *PtrlN)//X为插入的数字,i为插入的位置 { ListNode *p; if (i == 1)//删除结点在表头 { ListNode *s = PtrlN; if (PtrlN != NULL)PtrlN = PtrlN->Next; else return NULL; delete(s); //一定记住要释放链表中删除点的内存 return PtrlN; } p = FindKth(i - 1, PtrlN); if (p == NULL) { printf("参数i出错"); return NULL; } else if (p->Next == NULL) { printf("参数i出错"); return NULL; } else { ListNode *s = p->Next; p->Next = s->Next; delete(s); //注意,此处和上面一个语序不能颠倒,否则s的next还是s return PtrlN; } }
广义表:
- 线性表的推广;
- 广义表中元素可以是单元素也可以是另一个广义表
- union
多重链表:链表的节点可能同时隶属于多个链;结点的指针域会有多个;