1.线性表:线性表是n个具有相同特性的数据元素的有限序列。
线性表的主要存储结构:
顺序存储结构——顺序表
链式存储结构——链表
2.顺序存储:存储空间连续,用一组连续的存储单元依次存放数据元素;即逻辑上相邻的元素,其物理位置也相邻。
优点:随机存取
缺点:插入删除结点困难;扩展不灵活
3.链式存储:存储空间不必连续;即逻辑上相邻的元素,其物理位置可以任意,数据元素之间的逻辑关系借助指示元素存储位置的指针来表示。
链表的每个结点由两部分组成:数据域data、指针域*next
|| 线性表算法合集 ||
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef int ElemType;
struct SeqList{ //顺序表
ElemType *data; //数据域
int length; //表长
int maxSize; //能够存储的最大长度
SeqList(int size)//构造函数对成员变量做初始化
{
data = (ElemType *)malloc(size*sizeof(ElemType));//动态分配空间
length = 0;
maxSize = size;
}
};
typedef struct LNode{//单链表结点
ElemType data; //数据域
LNode* next;//指针域,指向下一个结点
LNode(ElemType d)//构造函数对成员变量做初始化
{
data = d;
next = NULL;
}
}*LinkList;
void show(SeqList L)
{
//显示顺序表
for(int i=0;i<L.length;i++)
{
printf("%d",L.data);
}
printf("\n");
}
void show(LNode *L)
{
//显示单链表
LNode *p = L->next;
while(p)
{
printf("%d",p->data);
p = p->next;
}
}
SeqList createSeqList(int *a,int n)
{
//根据长度为n的数组构造一个顺序表
SeqList L(n*2);
for(int i=0;i<n;i++)
{
L.data[i] = a[i];
}
L.length = n;
return L;
}
LinkList SeqListToLinkList(SeqList L)
{
LNode *h = (LinkList)malloc(sizeof(LNode)); //开辟一个结点空间作为头结点
h->data = NULL;
LNode *r = h;//尾指针
for(int i=0;i<L.length;i++)
{
LNode *p = (LinkList)malloc(sizeof(LNode));//开辟一个结点空间
p->data = L.data[i];
//初始化
p->next = NULL;
r->next = p;
//尾插法
r = p;//更新尾指针
}
return h; //返回头结点
}
//删除线性表中元素为X的值
void deleteX(SeqList& L,ElemType x)
{
//删除顺序表中L的值为X的元素
int j = 0; //将不等于x的元素放在区间[0,j)尾部
for(int i=0;i<L.length;i++)
{
if(L.data[i]!=x)
{
L.data[j++] = L.data[i];//将不等于x的元素插入区间[0,j)尾部,并且增加区间长度
}
}
L.length = j; //更新表长
}
//删除单链表中的值为x的元素
void deleteX(LinkList L,ElemType x)
{
LNode *p = L; //扫描指针
while(p->next)
{
if(p->data == x)
{
LNode *q = p->next;
p->next = q->next;//删除了q结点(链表上)
free(q); //释放空间
}else{ //否则p往后检查
p = p->next;
}
}
}
//去掉有序线性表中相同的元素
void deleteSame(SeqList &L)
{
//删除升序顺序表L中相同的元素
int j = 0;
for(int i=0;i<L.length;i++) //将保留元素放在[0,j]
{
if(L.data[j] != L.data[i]) //如果发现相邻不一样的元素
L.data[++j] = L.data[i];
}
L.length = j+1;
}
void reverse1(SeqList L)
{
//反转顺序表
for(int i=0;i<L.length/2;i++)
{
ElemType tmp = L.data[i];
L.data[i] = L.data[L.length-1-i];//将第i个元素和倒数第i个元素交换
L.data[L.length-1-i] = tmp;
}
}
void reverse2(LinkList L)
{
//反转链表
LNode *p = L->next; //扫描指针
LNode *r = NULL; //原链表中p的前驱
LNode *q = NULL; //原链表中p的后继
while(p)
{
q = p->next; //先保存p的后继
p->next = r;//反转链表
r = p;
p = q;
}
L->next = r; //最后一个结点成为第一个结点
}
void reverse(LinkList L)
{
//反转单链表L
LNode *p = L->next; //扫描指针
L->next = NULL; //单独拿出头结点
while(p)
{
LNode *q = p->next; //记录p的后继
p->next = L->next;//用头插法插入L链表中
L->next = p;
p = q; //往后移
}
}
void reverse(SeqList L,int l,int h)
{
//转置区间L(l,h)的元素
for(int i=0;i<(h-1)/2;i++)
{
swap(L.data[l+i],L.data[h-1-i]);//交换前第i个和后第i个
}
}
void ReLeftShift(SeqList L,int n)
{
//循环左移n个元素
n = n % L.length; //因为循环左移length个元素就相当于没移动
reverse(L,0,n);
reverse(L,n,L.length);
reverse(L,0,L.length);
}
int getLength(LinkList L)
{
//得到单链表L的长度
int len = 0;
LNode *p = L->next;
while(p)
{
len++;
p = p->next;
}
return len;
}
void ReLeftShift(LinkList L,int n)
{
//循环左移n个元素
n = n % getLength(L);//循环左移length个元素就相当于没移动
LNode *p = L;//第n个结点的前驱
for(int i=0;i<n;i++)
p = p->next;
LNode *q = p;//尾指针
while(q->next)
q = q->next;
q->next = L->next; //这三句话的顺序建议在纸上画一下,保证不断连接
L->next = p->next;
p->next = NULL;
}
SeqList merge(SeqList L1,SeqList L2)
{
//归并两个升序线性表L1和L2并放回结果
SeqList L(L1.length+L2.length);
int i = 0,j = 0;//扫描L1和L2的指针
int k = 0; //已经归并好的元素个数
while(i<L1.length || j<L2.length)
{
if(j>=L2.length || i<L1.length && L1.data[i]<=L2.data[j])
{
//拿取L1首元素情况;L2已经拿完或者L1没有拿完并且L1首元素比L2首元素小
L.data[k++] = L1.data[i++];
}else{
L.data[k++] = L2.data[j++];
}
}
L.length = k; //修改L的长度
return L;
}
void merge(LinkList L1,LinkList L2)
{
//归并两个升序单链表L1和L2将结果保存在L1中
LNode *p = L1->next,*q = L2->next;
LNode *r = L1; //合并以后的链表尾部
while(p&&q)
{
if(p->data <= q->data)
{
//比较p和q的值,将较小的值插到r后面
r->next = p; //尾插法插入
r = p;
p = p->next;
}else{
r->next = q;
r = q;
q = q->next;
}
}
if(p)
r->next = p;
else
r->next = q;
}
//将所有元素偶数元素放到奇数之前
void preOdd(SeqList L)
{
int i = 0,j = L.length -1;
int tmp = L.data[i];
while(i<=j)
{
while(i<=j && L.data[j]%2==1) //在后半区间找一个偶数
j--;
L.data[i] = L.data[j];//放到前面
while(i<=j&&L.data[i]%2==0) //在前半区间找一个奇数
i++;
L.data[j] = L.data[i];
}
L.data[i] = tmp;
}
void preOdd2(SeqList L)
{
int j = 0;//[0,j)保存偶数
for(int i=0;i<L.length;i++)//扫描所有元素
{
if(L.data[i] % 2 == 0)
{
swap(L.data[j],L.data[i]);
j++;
}
}
}
int kth(SeqList L,int k,int l,int h)
{
//在区间[l,h]中找第k个元素
if(l>h)
return -1;
int i = l,j = h; //前后扫描指针
int tmp = L.data[l]; //枢轴元素保存
while(i<j)
{
while(i<j && L.data[j]>=tmp)
j--;//寻找一个比tmp小的元素
L.data[i] = L.data[j];
while(i<j && L.data[i]<=tmp)
i++;
L.data[j] = L.data[i];
}
L.data[i] = tmp;
//show(L);
//printf("l=%d,h=%d,i=%d,a[i]=%d\n",l,h,i,L.data[i]);
if(i==k)
return L.data[k];//如果刚好是第k个
else if(k<i)
return kth(L,k,i+1,h);
//kth(L,k,l,i-1);
//kth(L,k,i+1,h);
}
int main()
{
int a[] = {1,10,9,8,4,6,3,2,5,7};
SeqList L = createSeqList(a,10);
//show(L);
int k = kth(L,3,0,L.length-1);
printf("%d\n",k);
//show(L);
//LinkList LL1 = SeqListToLinkList(L1);
//LinkList LL2 = SeqListToLinkList(L2);
//show(L);
//merge(LL1,LL2);
//show(LL1);
system("pause");
return 0;
}